熟悉IoC容器的都知道,在开发过程中,最郁闷的莫过于当你新增一个Service时,你需要对该Service进行注册,有的是使用代码注入,有的是XML配置注入,不管是哪种类型的注入,经常会出现开发人员忘记注入的情况,
如果你的页面是直接发送请求的,那么会得到类似于如下页面的错误:
如果该服务是用于AJAX请求实用的,那么你就悲剧了,因为页面只是没反应,只有查看错误日志了。
于是我试着去想办法去避免每次的服务都需要注入,而是系统自动注入。
红色线条框住的地方就是自动注入的代码实现。很高兴Autofac提供一个RegisterAssemblyTypes方法。它回去扫描所有的dll并把每个类注册为它所实现的接口。。。。
既然能够自动注入,那么接口和类的定义一定要有一定的规律。 从上面的代码可以看到baseType这个变量,它是IDependency接口的类型。
IDependency接口如下:
其他任何的接口都需要继承这个接口,例如我们定义一个接口IModelCar:
IModelCar的实现类:
自动注入原理说明:
首先我们去找到所有Dll,再去找到实现了IDependency接口的类,然后使用RegisterAssemblyTypes进行注入。
在Controller中调用试试:
可以看到_carmodel解析后为ModelCar的实例。。 ![]()
Demo下载: https://github.com/nicholaspei/MvcApplication5
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 }
1.
然后,就是将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();
1.
1.
1.






277

被折叠的 条评论
为什么被折叠?



