【反射】——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(); 


 

 

 


 

posted @ 2014-05-28 13:59  我佛慈悲纠结  阅读(3008)  评论(4编辑  收藏  举报