為了程序的健壯性、擴展性、可維護性,依賴抽象而不是具體實現類等等,于是我選擇了Autofac依賴注入容器 就是這個工廠來降低耦合。之前買東西是自己去超市,現在呢 我需要什么東西,他們給送過來直接拿到了。
本例中將會分享
1.Autofac在Mvc的Controller控制器、Filter過濾器的使用
2.WCF中的使用
3.用Autofac來完成Unit Of Work工作單元模式 即同一個界限上下文內可以共享同一個工作單元實例。這樣就可以統一提交,起到事務作用、數據統一性。一個http請求只有一個上下文實例也算是性能優化吧, 在這里只用到工作單元的一些皮毛。
Demo全貌如下
其中Repository、UnitOfWork、CoreService幾者之間調用接口或對供其他層調用接口。
從nuget獲取必要的Autofac程序包 Autofac、Autofac.Configuration、Autofac.Integration.Mvc、Autofac.Integration.Wcf
各個層依賴的是接口而不是具體實現類,Autofac是個工廠可以通過編譯的代碼和xml配置文件兩種方式指定接口、實現類來完成注入實例。
這里用的是xml配置的方式,需要用到Autofac.Configuration程序集。這樣做有個明顯的好處:文件不需要編譯;不會擾亂各層關系。為什么這么說呢?如果用代碼來完成,web層就需要其他層的接口和實現類 也就是引用Repository、UnitOfWork、CoreService層,很明顯web層只需要引用Autofac.Controllers 就足夠了。而通過xml配置文件可以在bin目錄下找到具體的程序集如:Autofac.CoreService.dll
Autoface依賴注入在MVC里實現
Global.cs
PRotected void application_Start() { //創建IOC容器 AutofacRegistion.BuildMvcContainer(); AutofacRegistion.BuildWcfContainer(); AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); }
/// <summary> /// 依賴注入Controller、FilterAtrribute、WCF /// </summary> public class AutofacRegistion { /// <summary> /// 創建 MVC容器(包含Filter) /// </summary> public static void BuildMvcContainer() { var builder = new ContainerBuilder(); //注冊Module方法2 在Web.config中配制方式 builder.RegisterModule(new ConfigurationSettingsReader("autofacMvc")); //加載 *.Controllers 層的控制器,否則無法在其他層控制器構造注入,只能在web層注入 Assembly[] asm = GetAllAssembly("*.Controllers.dll").ToArray(); builder.RegisterAssemblyTypes(asm); //注冊倉儲 Assembly[] asmRepository = GetAllAssembly("*.Repository.dll").ToArray(); builder.RegisterAssemblyTypes(asmRepository) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces();
//注入邏輯層也可以通過配置實現 //Assembly[] asmRepositoryService = GetAllAssembly("*.CoreService.dll").ToArray(); //builder.RegisterAssemblyTypes(asmRepositoryService).AsImplementedInterfaces();
builder.RegisterControllers(Assembly.GetExecutingAssembly()); builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); builder.RegisterModelBinderProvider(); //注冊過濾器 builder.RegisterFilterProvider(); builder.RegisterType<OperateAttribute>().PropertiesAutowired(); builder.RegisterControllers(typeof(MvcApplication).Assembly); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } /// <summary> ///創建WCF的容器,不存放Controller、Filter /// </summary> public static void BuildWcfContainer() { var builder = new ContainerBuilder(); builder.RegisterModule(new ConfigurationSettingsReader("autofacWcf")); builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); builder.RegisterModelBinderProvider(); var container = builder.Build(); //WCF IOC容器 AutofacHostFactory.Container = container; //DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } #region 加載程序集 public static List<Assembly> GetAllAssembly(string dllName) { List<string> pluginpath = FindPlugin(dllName); var list = new List<Assembly>(); foreach (string filename in pluginpath) { try { string asmname = Path.GetFileNameWithoutExtension(filename); if (asmname != string.Empty) { Assembly asm = Assembly.LoadFrom(filename); list.Add(asm); } } catch (Exception ex) { Console.Write(ex.Message); } } return list; } //查找所有插件的路徑 private static List<string> FindPlugin(string dllName) { List<string> pluginpath = new List<string>(); string path = AppDomain.CurrentDomain.BaseDirectory; string dir = Path.Combine(path, "bin"); string[] dllList = Directory.GetFiles(dir, dllName); if (dllList.Length > 0) { pluginpath.AddRange(dllList.Select(item => Path.Combine(dir, item.Substring(dir.Length + 1)))); } return pluginpath; } #endregion }
說明:
1 web.config還需要配置 globlal代碼中對應的【autofacMvc】和【autofacWcf】節點
2 反射*.Controllers.dll獲取Autofac.Controllers程序集,實現注入
3反射*.Repository.dll獲取 Autofac.Repository程序集以'Repository'結尾的類的實例注入到它所繼承的接口,這個就不需要在xml中配置
4filter的注入和controller的注入方式不一樣
5 MVC和WCF注入實例分別存到兩個容器中。這就用到Autofac.Integration.Mvc、Autofac.Integration.Wcf兩個程序集。WCF注入的容器中不需要Controller、Filter,就可以把相關的反射和注冊去掉了。
web.config
<configSections> <!-- autofac配置--> <section name="autofacMvc" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /> <section name="autofacWcf" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /> </configSections> <autofacMvc> <files> <file name="configs/CoreService.config" section="autofac" /> </files> </autofacMvc> <autofacWcf> <files> <!--<file name="configs/IocDAL.config" section="autofac" />--> </files> </autofacWcf> <!--↑↑↑↑autofac配置結束↑↑↑↑-->
在上述webconfig中為了統一管理配置,具體指定接口、實現類、和注入實例的生命周期放到了configs/CoreService.config文件中
CoreService.config
<?xml version="1.0" encoding="utf-8"?><configuration> <configSections> <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/> </configSections> <autofac> <components> <!--DbContext上下文的生命周期為【per-lifetime-scope】即http請求的生命周期 --> <component type="Autofac.DataModel.VehicleCheckDBEntities, Autofac.DataModel" service="System.Data.Entity.DbContext, EntityFramework" instance-scope="per-lifetime-scope"/> <component type="Autofac.UnitOfWork.UnitOfWork, Autofac.UnitOfWork" service="Autofac.UnitOfWork.IUnitOfWork, Autofac.UnitOfWork" /> <component type="Autofac.CoreService.Impl.UserManage, Autofac.CoreService" service="Autofac.CoreService.IUserManage, Autofac.CoreService" /> <component type="Autofac.CoreService.Impl.RoleManage, Autofac.CoreService" service="Autofac.CoreService.IRoleManage, Autofac.CoreService" /> </components> </autofac></configuration>
說明:
1component組件配置中type、service配置的是實現類、程序集名稱(不是命名空間)、接口、程序集名稱。
2instance-scope 配置的是實例的生命周期。本例中用到兩種:
新聞熱點
疑難解答