1、前言
Autofac是.NET領域最爲流行的IOC框架之一,微軟的Orchad開源程序使用的就是Autofac,Nopcommerce開源程序也是用的Autofac。html
Orchad和Nopcommerce在用Autofac的時候進行封裝,看過源碼的都知道Autafac使用簡單,功能強大。web
建議下載Orchad和Nopcommerce學習下源碼:附上下載地址數據庫
http://www.orchardproject.net/編程
http://www.nopcommerce.com/api
和其餘IOC對比:安全
Unity:微軟patterns&practicest團隊開發的IOC依賴注入框架,支持AOP橫切關注點。mvc
MEF(Managed Extensibility Framework):是一個用來擴展.NET應用程序的框架,可開發插件系統。app
Spring.NET:依賴注入、面向方面編程(AOP)、數據訪問抽象,、以及ASP.NET集成。框架
PostSharp:實現靜態AOP橫切關注點,使用簡單,功能強大,對目標攔截的方法無需任何改動。函數
Autofac:最流行的依賴注入和IOC框架,輕量且高性能,對項目代碼幾乎無任何侵入性。
下面介紹Autofac的使用
2、Autofac使用
新建一個mvc的項目,使用nuget安裝Autofac,須要安裝Autofac和Autofac ASP.NET MVC5 Intergration
安裝完成後引用裏面就多了Autofac.dll和Autofac.Intergration.MVC,若是是在webApi裏使用Autofac須要安裝Autofac ASP.NET Web API2.2 Intergration 才能夠。
新建一個person實體類
public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } }
新建一個person倉儲接口
public interface IPersonRepository { IEnumerable<Person> GetAll(); Person Get(int id); Person Add(Person item); bool Update(Person item); bool Delete(int id); }
新建實現
public class PersonRepository : IPersonRepository { List<Person> person = new List<Person>(); public PersonRepository() { Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中國上海" }); Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中國上海" }); Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中國上海" }); } public IEnumerable<Person> GetAll() { return person; } public Person Get(int id) { return person.Find(p => p.Id == id); } public Person Add(Person item) { if (item == null) { throw new ArgumentNullException("item"); } person.Add(item); return item; } public bool Update(Person item) { if (item == null) { throw new ArgumentNullException("item"); } int index = person.FindIndex(p => p.Id == item.Id); if (index == -1) { return false; } person.RemoveAt(index); person.Add(item); return true; } public bool Delete(int id) { person.RemoveAll(p => p.Id == id); return true; } }
Global屬性注入
public class MvcApplication : System.Web.HttpApplication { private void SetupResolveRules(ContainerBuilder builder) { builder.RegisterType<PersonRepository>().As<IPersonRepository>(); } protected void Application_Start() { var builder = new ContainerBuilder(); SetupResolveRules(builder); builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired(); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } }
最好獲取數據結果;
3、總結
文中只是給出了一個簡單的注入實現,剩下的能夠本身去研究下,構造函數注入,方法注入
泛型注入,全部程序集註入,均可以看下,
也能夠把文章開頭的兩個開源的項目下載下來研究裏面的Autofac注入方式。
WebAPI2使用Autofac實現IOC屬性注入完美解決方案
1、前言
只要你是.NETer你必定IOC,IOC裏面你也會必定知道Autofac,上次說了在MVC5實現屬性注入,今天實如今WebApi2實現屬性注入,順便說一下autofac的程序集的注入方式,都會在後面的代碼裏面有提現
在WebAPI2使用Autofac注入的時候大多數人會出現以下問題:
未能加載文件或程序集「System.Web.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35」或它的某一個依賴項。找到的程序集清單定義與程序集引用不匹配。 (異常來自 HRESULT:0x80131040)
截圖以下:
這個是Autofac強依賴形成的,比較坑的。解決辦法以下。
Nuget添加Microsoft.AspNet.WebApi
或經過NuGet 程序包管理器控制檯添加:
Install-Package Microsoft.AspNet.WebApi
Update-Package Microsoft.AspNet.WebApi -reinstall(存在)
緣由:咱們新建的是一個空的MVC項目,缺乏引用
先上個結構圖,結構圖只是爲了說明webAPI如何簡單使用Autofac實現屬性注入。
屬性注入存在安全隱患,官方建議使用構造函數注入。
下面說下具體實現:
2、代碼實現
一、新建一個WebAPI.Entity類庫,新建一個Person.cs類
public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } }
二、新建WebAPI.IRepository類庫,新建一個IPersonRepository類
public interface IPersonRepository { List<Person> GetAll(); Person Get(int id); Person Add(Person item); bool Update(Person item); bool Delete(int id); }
三、新建WebAPI.Repository類庫,新建一個PersonRepository類實現IPersonRepository接口
public class PersonRepository : IPersonRepository { List<Person> person = new List<Person>(); public PersonRepository() { Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中國上海" }); Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中國上海" }); Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中國上海" }); } public List<Person> GetAll() { return person; } public Person Get(int id) { return person.Find(p => p.Id == id); } public Person Add(Person item) { if (item == null) { throw new ArgumentNullException("item"); } person.Add(item); return item; } public bool Update(Person item) { if (item == null) { throw new ArgumentNullException("item"); } int index = person.FindIndex(p => p.Id == item.Id); if (index == -1) { return false; } person.RemoveAt(index); person.Add(item); return true; } public bool Delete(int id) { person.RemoveAll(p => p.Id == id); return true; } }
四、新建WebAPI.IServices類庫,新建IPersonServices接口
public interface IPersonServices { List<Person> GetAll(); }
五、IPersonServices接口在WebAPI.Services類庫裏面PersonServices實現
public class PersonServices : IPersonServices { //程序集屬性注入 public IPersonRepository iPerson; public List<Person> GetAll() { return iPerson.GetAll(); } }
六、新建一個WebAPI項目WebAPI,新建AutoFacBootStrapper類,nuget安裝autofac
public class AutoFacBootStrapper { public static void CoreAutoFacInit() { var builder = new ContainerBuilder(); HttpConfiguration config = GlobalConfiguration.Configuration; SetupResolveRules(builder); ////註冊全部的Controllers //builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired(); //註冊全部的ApiControllers builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired(); var container = builder.Build(); //註冊api容器須要使用HttpConfiguration對象 config.DependencyResolver = new AutofacWebApiDependencyResolver(container); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } private static void SetupResolveRules(ContainerBuilder builder) { //WebAPI只用引用services和repository的接口,不用引用實現的dll。 //如需加載實現的程序集,將dll拷貝到bin目錄下便可,不用引用dll var iServices = Assembly.Load("WebAPI.IServices"); var services = Assembly.Load("WebAPI.Services"); var iRepository = Assembly.Load("WebAPI.IRepository"); var repository = Assembly.Load("WebAPI.Repository"); //根據名稱約定(服務層的接口和實現均以Services結尾),實現服務接口和服務實現的依賴 builder.RegisterAssemblyTypes(iServices, services) .Where(t => t.Name.EndsWith("Services")) .AsImplementedInterfaces(); //根據名稱約定(數據訪問層的接口和實現均以Repository結尾),實現數據訪問接口和數據訪問實現的依賴 builder.RegisterAssemblyTypes(iRepository, repository) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces(); } }
七、程序啓動注入
protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); BundleConfig.RegisterBundles(BundleTable.Bundles); //程序啓動注入 AutoFacBootStrapper.CoreAutoFacInit(); }
8.接口調用數據
public IPersonServices IServices { get; set; } // GET api/<controller> public IEnumerable<string> Get() { var list = IServices.GetAll(); return new string[] { "value1", "value2" }; }
9.運行訪問api/values/,打個斷點看下搞定
3、總結
autofac確實用起來很方便,上面只是簡單的實現,若是想深刻學習能夠下載我上一個文章提供的兩個開源的項目能夠學習下,也能夠到autofac官網去了解下。
最近在看相關文章,不少都太專業化了沒怎麼看懂,這是本身如今對IoC的一些理解,記錄下來,要否則時間一久,也就忘了。
本身對IoC模式理解還很淺,但願獲得各位的指點。
代碼下載:
https://yunpan.cn/c6QCURhYmGcP9 (提取碼:e97a)
AutoFac容器初步
轉載請註明出處,AutoFac:最流行的依賴注入和IOC框架,輕量且高性能,對項目代碼幾乎無任何侵入性。
那麼咱們怎麼來使用這樣一個框架呢
一、在引用項右擊,選擇Nuget管理,這裏咱們要導入兩個包
一個是AutoFac包,另一個就是Autofac ASP.NET MVC5 Intergration
在webapi裏面使用的話咱們須要添加一個Autofac ASP.NET Web API2.2 Intergration 才能夠。
2.Global.asax.cs屬性注入,配置IOC容器,我這裏配置的是通用的以I開頭的Repository(倉庫類)
#region autofac IOC容器配置 var builder = new ContainerBuilder(); //註冊全部的controller builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired(); //註冊全部模塊module builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray(); //註冊全部繼承IDependency接口的類 builder.RegisterAssemblyTypes(assemblys) .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract); //註冊服務,全部IxxxxRepository=>xxxxRepository builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces(); var container = builder.Build(); BaseInfo._container = container; DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); #endregion
3.新建實體基類以及實體類,也就是建立數據模型
base類:
public class BaseEntity { [NotMapped] [PropertyModelBinder("start")] public int pageIndex { get; set; } [NotMapped] [PropertyModelBinder("length")] public int pageSize { get; set; } [NotMapped] public string draw { get; set; } [NotMapped] public List<Orderby> order { get; set; } [NotMapped] public List<Datacolumn> columns { get; set; } } public class Orderby { public string column { get; set; } public string dir { get; set; } } public class Datacolumn { public string data { get; set; } public string name { get; set; } public bool searchable { get; set; } public bool orderable { get; set; } }
實體類:
public class User : BaseEntity { public User() { RoleList = new List<Role>(); MessageList = new List<UserMappingMessage>(); } public int UserID { get; set; } public string UserName { get; set; } public string UserPassword {get;set;} public string UserReallyname {get;set;} public string HeadPortrait { get; set; } public string MobilePhone { get; set; } public string Email { get; set; } public int DepartmentID {get;set;} public bool IsEnable {get;set;} public DateTime CreateTime {get;set;} public DateTime? UpdateTime {get;set;} public string Remark { get; set; } public ICollection<Role> RoleList { get; set; } //接收消息列表 public ICollection<UserMappingMessage> MessageList { get; set; } public Dictionary Department { get; set; } //發送消息列表 public List<Message> Messages { get; set; } }
4.建立倉儲接口,由於我在配置Global屬性時,已經說明了我要注入全部以 「I」 開頭的接口,那麼我就把這個用戶的接口給定義爲IUserRepository
固然,不一樣的實體類所須要的倉儲接口也不同,這裏根據本身的實際需求去寫須要的方法類,接口嘛,就不要在這裏具體實現你的方法了
public interface IUserRepository { Tuple<int,List<User>> GetList(User model); List<User> GetUserInfos(); User GetSingle(User model); User GetbyID(int userID); void AddUser(User model); void ModifyUser(User model); void DeleteUser(User model); void SetUserInfoRole(int userID, List<int> roleIDList); List<AutoUserDo> GetUserInfobyName(string value); void ResetUserPWDbyID(int id); }
5.咱們定義一個實現接口的類,而後把接口的方法給實現,這裏面就是對數據實體進行操做了
public class UserRepository : IUserRepository { public Tuple<int, List<User>> GetList(User model) { using (UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>()) { var SysUserRepository = dal.GetRepository<User>(); var conditions = ExpandHelper.True<User>(); if (!string.IsNullOrEmpty(model.UserName)) conditions = conditions.And(a => a.UserName.Contains(model.UserName)); if (!string.IsNullOrEmpty(model.UserReallyname)) conditions = conditions.And(a => a.UserReallyname.Contains(model.UserReallyname)); if (model.DepartmentID > 0) conditions = conditions.And(a => a.DepartmentID == model.DepartmentID); var templist = SysUserRepository.Get(filter: conditions, includeProperties: "RoleList"); var count = templist.Count(); if (model.order != null&&model.order.Count()>0) { foreach (var item in model.order) { var column = model.columns.ElementAt(int.Parse(item.column)); templist = templist.OrderSort(column.data, item.dir); } } var result = templist.PageBy(model.pageIndex, model.pageSize).ToList(); return new Tuple<int, List<User>>(count, result); } } public User GetSingle(User model) { using(UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>()){ var conditions = ExpandHelper.True<User>(); if (!string.IsNullOrEmpty(model.UserName)) conditions = conditions.And( a => a.UserName == model.UserName || a.MobilePhone == model.UserName); if (!string.IsNullOrEmpty(model.MobilePhone)) conditions = conditions.And(a => a.MobilePhone == model.MobilePhone); var result = dal.GetRepository<User>().Get(conditions).FirstOrDefault(); return result; } } public User GetbyID(int userID) { using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>()) { // var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID, includeProperties: "RoleList.MenuList,RoleList.rbList").AsNoTracking().FirstOrDefault(); var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID,includeProperties: "RoleList").FirstOrDefault(); foreach (var item in result.RoleList) { var role=dal.GetRepository<Role>().Get(a=>a.RoleID==item.RoleID,includeProperties:"MenuList,rbList").FirstOrDefault(); item.MenuList = role.MenuList; item.rbList = role.rbList; } return result; } } public void AddUser(User model) { using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>()) { dal.GetRepository<User>().Insert(model); dal.Save(); } } public void ModifyUser(User model) { using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>()) { dal.GetRepository<User>().UpdateSup(model, new List<string>() { "IsEnable", "CreateTime" }, false); dal.Save(); } } public void DeleteUser(User model) { using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>()) { var sysUserRepository= dal.GetRepository<User>(); var Usermodel = sysUserRepository.GetByID(model.UserID); Usermodel.IsEnable=Usermodel.IsEnable?false:true; sysUserRepository.UpdateSup(Usermodel, new List<string>() { "IsEnable" }); dal.Save(); } } /// <summary> /// 添加用戶角色信息,先刪除原有數據,在添加到數據庫 /// </summary> /// <param name="userID"></param> /// <param name="roleIDList"></param> /// <returns></returns> public void SetUserInfoRole(int userID, List<int> roleIDList) { using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>()) { var sysUserRepository = dal.GetRepository<User>(); var roleRepository = dal.GetRepository<Role>(); var UserModel = GetbyID(userID); var roleList = UserModel.RoleList.ToList(); roleList.ForEach(m => { var userModel = sysUserRepository.Get(filter: a => a.UserID == userID, includeProperties: "RoleList").FirstOrDefault(); var roleModel = roleRepository.GetByID(m.RoleID); userModel.RoleList.Remove(roleModel); }); roleIDList.ForEach(m => { var userModel = sysUserRepository.GetByID(userID); var roleModel = roleRepository.GetByID(m); userModel.RoleList.Add(roleModel); }); dal.Save(); } } public List<AutoUserDo> GetUserInfobyName(string value) { Mapper.Initialize(a => { a.CreateMap<User, AutoUserDo>() .ForMember(au => au.id, op => { op.MapFrom(user => user.UserID); }) .ForMember(au => au.text, op => { op.MapFrom(user => user.UserReallyname); }) .ForMember(au => au.department, op => { op.MapFrom(user => user.Department.DicValue); }); a.CreateMap<Role, roleinfo>(); }); using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) { return dal.GetRepository<User>() .Get(a => a.UserReallyname.Contains(value) || a.MobilePhone == value, includeProperties: "Department,Role").ProjectToQueryable<AutoUserDo>().ToList(); } } public void ResetUserPWDbyID(int id) { using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) { var repository = dal.GetRepository<User>(); var usermodel = new User() { UserID = id, UserPassword = "123456" }; repository.UpdateSup(usermodel, new List<string>() { "UserPassword" }); dal.Save(); } } public List<User> GetUserInfos() { using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) { return dal.GetRepository<User>().Get().ToList(); } } }
6.而後咱們就能夠在MVC的控制器裏面去調用這些方法來實現咱們所想要的功能了,我這裏只展現一個方法
public void SendEmailAsync(Message model) { Task.Run(() => { try { var reclist = string.Empty; foreach (var item in model.RecUser.Split(',')) { var userinfo = this.UserRepository.GetbyID(int.Parse(item)); //這裏就調用了實現接口的那個類的方法,去驗證用戶的ID if (!string.IsNullOrEmpty(userinfo.Email)) { reclist += userinfo.Email + ","; } } if (!string.IsNullOrEmpty(reclist)) { reclist = reclist.Substring(0, reclist.Length - 1); EmailHelper email = new EmailHelper(reclist, model.MessageTitle, model.MessageText); email.Send(); } model.SendEmailState = 2; this.MessageServer.SetSendState(model); }catch(Exception ex){ new LogHelper().LogError("發送郵件異常" + ex); model.SendEmailState = 3; this.MessageServer.SetSendState(model); } }); }
那麼整個流程就是這樣,看着別人寫的那些博客裏面的流程不是那麼的全面,我這裏就詳細的把AutoFac的整個流程給梳理出來了,有不對的地方請及時指出
後面我會詳細說明一下Unity IOC框架是如何使用的,這裏我就再也不敘述了
下面是兩篇比較好的博文,我以爲比較有參考意義的,能夠看一下,喜歡我發佈的內容的能夠關注我,後面還會有其餘的乾貨和內容進行分享
.NET領域最爲流行的IOC框架之一Autofac:https://www.cnblogs.com/yinrq/p/5381492.html
.NET Unity IOC框架使用實例:https://blog.csdn.net/chen_peng7/article/details/54896449