【反射】——Autofac 類型注冊


  Autofac是.net界一款輕量化的IOC組件,使用Autofac可以幫助完成代碼中很多依賴注入工作。在以前文章中,介紹過Autofac的配置過程(http://www.cnblogs.com/Jnw-qianxi/p/3450344.html),在我以往的配置過程中,接口與接口的實現類的注冊在一個靜態方法RegisterAutofac中實現:

 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注冊區域中會不斷添加新的注冊,不同區域,不同模塊的類型注冊都會在這進行(數據倉儲層,業務邏輯層,基礎設施層等等不同層次的類型注冊都要在此方法中進行),同時系統不同開發人員都需要維護該方法,這樣帶來

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注冊區域移除到類當中

 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()方法中調用上述方法

 1 ContainerManager.InitContainer(); 


 

 

 
 
        
 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM