Autofac是.net界一款輕量化的IOC組件,使用Autofac能夠幫助完成代碼中不少依賴注入工做。在之前文章中,介紹過Autofac的配置過程(http://www.cnblogs.com/Jnw-qianxi/p/3450344.html),在我以往的配置過程當中,接口與接口的實現類的註冊在一個靜態方法RegisterAutofac中實現:html
1 public static void RegisterAutofac() 2 { 3 ContainerBuilder builder = new ContainerBuilder(); 4 builder.RegisterControllers(Assembly.GetExecutingAssembly()); 5 6 #region IOC註冊區域 7 8 9 //Admin 10 builder.RegisterType<AdminService>().As<IAdminService>().InstancePerHttpRequest(); 11 12 13 #endregion 14 // then 15 var container = builder.Build(); 16 DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 17 18 }
隨着系統開發的進行,IOC註冊區域中會不斷添加新的註冊,不一樣區域,不一樣模塊的類型註冊都會在這進行(數據倉儲層,業務邏輯層,基礎設施層等等不一樣層次的類型註冊都要在此方法中進行),同時系統不一樣開發人員都須要維護該方法,這樣帶來ui
RegisterAutofac方法所在類的臃腫,且不符合類的職責單一原則。
爲此我想到,可否根據註冊類型,將IOC註冊區域部分提取到不一樣的類中實現,將如這些類擁有一個共同的接口,不是就能夠根據接口反射出獲取這些類了嗎?
首先,定義反射類。用於獲取繼承接口的類型
1 public class ContainerTypeFinder : ITypeFinder 2 { 3 4 public IList<Assembly> GetAssemblies() 5 { 6 //因爲註冊文件可能分佈在不一樣類庫,爲此咱們獲取全部程序集,而不是當前程序集 7 return AppDomain.CurrentDomain.GetAssemblies(); 8 9 } 10 11 public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom) 12 { 13 var list = new List<Type>(); 14 foreach (var item in GetAssemblies()) 15 { 16 var typesToRegister = item.GetTypes() 17 .Where(type => !String.IsNullOrEmpty(type.Namespace)) 18 .Where(type => type.GetInterface(assignTypeFrom.Name) == assignTypeFrom) 19 ; 20 if (typesToRegister.Count() > 0) 21 { 22 list.AddRange(typesToRegister); 23 } 24 } 25 return list; 26 } 27 }
而後,就是將IOC註冊區域移除到類當中spa
1 public interface IDependencyRegistrar 2 { 3 void Register(ContainerBuilder builder); 4 5 int Order { get; } 6 } 7 8 9 public class DependencyRegistrar : IDependencyRegistrar 10 { 11 public void Register(ContainerBuilder builder) 12 { 13 builder.RegisterType<EfRepository<Core.Domain.Customer.Customer>>().As<IRepository<Core.Domain.Customer.Customer>>().InstancePerHttpRequest(); 14 } 15 16 public int Order 17 { 18 get { return 1; } 19 } 20 }
IDependencyRegistrar就是咱們上面所說的接口,ContainerTypeFinder類當中的FindClassesOfType()方法會搜尋全部實現該接口的類。實現的註冊工做在Register()方法中完成。
接着,封裝一個方法完成全部的Autofac註冊工做,同時便於在Global中調用:
1 public static void InitContainer() 2 { 3 //autofac 容器 4 ContainerBuilder builder = new ContainerBuilder(); 5 //註冊全部控制器 6 builder.RegisterControllers(_typeFinder.GetAssemblies().ToArray()); 7 8 #region 反射 核心 9 //經過反射獲得繼承IDependencyRegistrar該接口的類成員 10 var types = _typeFinder.FindClassesOfType(typeof(IDependencyRegistrar)); 11 var drInstances = new List<IDependencyRegistrar>(); 12 //建立實例 13 foreach (var drType in types) 14 drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(drType)); 15 //sort 16 drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList(); 17 //執行Register方法 18 foreach (var dependencyRegistrar in drInstances) 19 dependencyRegistrar.Register(builder); 20 #endregion 21 22 //then 23 var container = builder.Build(); 24 DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
最後在Global文件Application_Start()方法中調用上述方法.net
1 ContainerManager.InitContainer(); code