ASP.NET MVC中Autofac实现的自动注入模式

熟悉IoC容器的都知道,在开发过程中,最郁闷的莫过于当你新增一个Service时,你需要对该Service进行注册,有的是使用代码注入,有的是XML配置注入,不管是哪种类型的注入,经常会出现开发人员忘记注入的情况,

如果你的页面是直接发送请求的,那么会得到类似于如下页面的错误:

image  <- _<-

 

如果该服务是用于AJAX请求实用的,那么你就悲剧了,因为页面只是没反应,只有查看错误日志了。

 

于是我试着去想办法去避免每次的服务都需要注入,而是系统自动注入。

image

 

红色线条框住的地方就是自动注入的代码实现。很高兴Autofac提供一个RegisterAssemblyTypes方法。它回去扫描所有的dll并把每个类注册为它所实现的接口。。。。

既然能够自动注入,那么接口和类的定义一定要有一定的规律。 从上面的代码可以看到baseType这个变量,它是IDependency接口的类型。

IDependency接口如下:

image

 

其他任何的接口都需要继承这个接口,例如我们定义一个接口IModelCar:

image

 

IModelCar的实现类:

 

image

 

自动注入原理说明:

 

 

 

首先我们去找到所有Dll,再去找到实现了IDependency接口的类,然后使用RegisterAssemblyTypes进行注入。

 

在Controller中调用试试:

image

 

可以看到_carmodel解析后为ModelCar的实例。。 微笑

 

Demo下载: https://github.com/nicholaspei/MvcApplication5

 

标签:  Asp.net MVCAutofac

转载至http://www.cnblogs.com/n-pei/archive/2013/01/24/2875674.html

转载至http://www.it165.net/pro/html/201405/14502.html
原理

Autofac是.net界一款轻量化的IOC组件,使用Autofac可以帮助完成代码中很多依赖注入工作。在以前文章中,介绍过Autofac的配置过程(http://www.cnblogs.com/Jnw-qianxi/p/3450344.html),在我以往的配置过程中,接口与接口的实现类的注册在一个静态方法RegisterAutofac中实现:

01. 1 public static void RegisterAutofac()
02. 2         {
03. 3             ContainerBuilder builder = new ContainerBuilder();
04. 4             builder.RegisterControllers(Assembly.GetExecutingAssembly());
05. 5
06. 6             #region IOC注册区域
07. 7        
08. 8           
09. 9             //Admin
10. 10             builder.RegisterType<AdminService>().As<IAdminService>().InstancePerHttpRequest();
11. 11
12. 12        
13. 13             #endregion
14. 14             // then
15. 15             var container = builder.Build();
16. 16             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
17. 17          
18. 18         }

    随着系统开发的进行,IOC注册区域中会不断添加新的注册,不同区域,不同模块的类型注册都会在这进行(数据仓储层,业务逻辑层,基础设施层等等不同层次的类型注册都要在此方法中进行),同时系统不同开发人员都需要维护该方法,这样带来

1. RegisterAutofac方法所在类的臃肿,且不符合类的职责单一原则。<br><br>  为此我想到,能否根据注册类型,将IOC注册区域部分提取到不同的类中实现,将如这些类拥有一个共同的接口,不是就可以根据接口反射出获取这些类了吗?<br>  <br>首先,定义反射类。用于获取继承接口的类型
01. 1  public class ContainerTypeFinder : ITypeFinder
02. 2     {
03. 3
04. 4         public IList<Assembly> GetAssemblies()
05. 5         {
06. 6             //由于注册文件可能分布在不同类库,为此我们获取所有程序集,而不是当前程序集
07. 7             return AppDomain.CurrentDomain.GetAssemblies();
08. 8
09. 9         }
10. 10
11. 11         public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom)
12. 12         {
13. 13             var list = new List<Type>();
14. 14             foreach (var item in GetAssemblies())
15. 15             {
16. 16                 var typesToRegister = item.GetTypes()
17. 17               .Where(type => !String.IsNullOrEmpty(type.Namespace))
18. 18               .Where(type => type.GetInterface(assignTypeFrom.Name) == assignTypeFrom)
19. 19              ;
20. 20                 if (typesToRegister.Count() > 0)
21. 21                 {
22. 22                     list.AddRange(typesToRegister);
23. 23                 }
24. 24             }
25. 25             return list;
26. 26         }
27. 27     }

  然后,就是将IOC注册区域移除到类当中

01. 1  public interface IDependencyRegistrar
02. 2     {
03. 3         void Register(ContainerBuilder builder);
04. 4
05. 5         int Order { get; }
06. 6     }
07. 7
08. 8
09. 9  public class DependencyRegistrar : IDependencyRegistrar
10. 10     {
11. 11         public void Register(ContainerBuilder builder)
12. 12         {
13. 13             builder.RegisterType<EfRepository<Core.Domain.Customer.Customer>>().As<IRepository<Core.Domain.Customer.Customer>>().InstancePerHttpRequest();
14. 14         }
15. 15
16. 16         public int Order
17. 17         {
18. 18             get { return 1; }
19. 19         }
20. 20     }
1. IDependencyRegistrar就是我们上面所说的接口,ContainerTypeFinder类当中的FindClassesOfType()方法会搜寻所有实现该接口的类。实现的注册工作在Register()方法中完成。<br>接着,封装一个方法完成所有的Autofac注册工作,同时便于在Global中调用:<br>
01. 1 public static void InitContainer()
02. 2         {
03. 3             //autofac 容器
04. 4             ContainerBuilder builder = new ContainerBuilder();
05. 5             //注册所有控制器
06. 6             builder.RegisterControllers(_typeFinder.GetAssemblies().ToArray());
07. 7
08. 8             #region 反射 核心
09. 9             //通过反射得到继承IDependencyRegistrar该接口的类成员
10. 10             var types = _typeFinder.FindClassesOfType(typeof(IDependencyRegistrar));
11. 11             var drInstances = new List<IDependencyRegistrar>();
12. 12             //创建实例
13. 13             foreach (var drType in types)
14. 14                 drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(drType));
15. 15             //sort
16. 16             drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
17. 17             //执行Register方法
18. 18             foreach (var dependencyRegistrar in drInstances)
19. 19                 dependencyRegistrar.Register(builder);
20. 20             #endregion
21. 21
22. 22             //then
23. 23            var container = builder.Build();
24. 24            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

最后在Global文件Application_Start()方法中调用上述方法

 1 ContainerManager.InitContainer(); 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值