海水正蓝

面朝大海,春暖花开
posts - 145, comments - 29, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
对依赖注入( http://www.oschina.net/code/snippet_871522_15682) 的进一步加强.
作为基本功能的注册,使用语法是:registration.register<Interface,Implementation>().
可以到了实际的项目中,要注册的接口和类可能不止一个两个,会成百上千。无论是用C#代码来注册,还是用XML文件来配置,都是开发者的噩梦。

这里,让我们来个思维的反转: 变集中配置为分散声明。
1 为要注册的类,加入RegisterInContainer的声明
2 在系统启动的时候,扫描所有的类,对有RegisterInContainer的类,找到它所有实现的接口,把这些接口和该类绑定注册。

用于装饰要注入类的Attribute.


 1 using System;
 2 using System.Linq;
 3 using Skight.eLiteWeb.Domain.BasicExtensions;
 4 
 5 namespace Skight.eLiteWeb.Domain.Containers
 6 {
 7     [AttributeUsage(AttributeTargets.Class)]
 8     public class RegisterInContainerAttribute : Attribute
 9     {
10         public RegisterInContainerAttribute(LifeCycle life_cycle) {
11             this.life_cycle = life_cycle;
12         }
13 
14         public LifeCycle life_cycle { getset; }
15         public Type type_to_register_in_container { getset; }
16 
17         public void register_using(Registration registration) {
18             DiscreteItemResolver resolver = new TypeResolver(type_to_register_in_container);
19             if (life_cycle == LifeCycle.singleton) resolver = new SingletonResolver(resolver);
20             registration.register(resolver,type_to_register_in_container.all_interface().ToArray());
21         }
22     }
23 }

注入声明Attribute参数,指定是否单件方式生成注册类。


1 namespace Skight.eLiteWeb.Domain.Containers
2 {
3     public enum LifeCycle
4     {
5         single_call,
6         singleton
7     }
8 }

注册声明Attribute的使用示例


 1 //调用Container.get_an<FrontController>()将会得到FrontControllerImpl的对象
 2 
 3 using Skight.eLiteWeb.Domain.Containers;
 4 
 5 namespace Skight.eLiteWeb.Presentation.Web.FrontControllers
 6 {
 7     [RegisterInContainer(LifeCycle.single_call)]
 8     public class FrontControllerImpl : FrontControllers.FrontController
 9     {
10         private CommandResolver command_resolver;
11 
12         public FrontControllerImpl(CommandResolver commandResolver)
13         {
14             command_resolver = commandResolver;
15         }
16 
17         public void process(WebRequest request)
18         {
19             command_resolver.get_command_to_process(request).process(request);
20         }
21     }
22 }

Registration添加一个方法:反过来,为一个解析器(实现类)注册多个接口。


1 void register(DiscreteItemResolver resolver, params Type[] contracts);
2 

扫描注册机,在系统启动时调用一次。


 1 using System.Collections.Generic;
 2 using System.Reflection;
 3 using Skight.eLiteWeb.Domain.BasicExtensions;
 4 using Skight.eLiteWeb.Domain.Containers;
 5 
 6 namespace Skight.eLiteWeb.Application.Startup
 7 {
 8     public class RegistrationScanner:StartupCommand
 9     {
10         private readonly Registration registration;
11         private readonly IEnumerable<Assembly> assemblies;
12 
13         public RegistrationScanner(Registration registration, params Assembly[] assemblies)
14         {
15             this.registration = registration;
16             this.assemblies = assemblies;
17         }
18 
19         public void run()
20         {
21             assemblies
22                 .each(assembly =>
23                       assembly.GetTypes()
24                               .each(type =>
25                                     type.run_againste_attribute<RegisterInContainerAttribute>(
26                                         attribute =>
27                                             {
28                                                 attribute.type_to_register_in_container = type;
29                                                 attribute.register_using(registration);
30                                             })));
31         }
32     }
33 }

系统启动:创建注册类,然后传入必要的Assembly,调用注册机注册所有加了Attribute的类。


 1 using System;
 2 using System.Collections.Generic;
 3 using System.Reflection;
 4 using Skight.eLiteWeb.Domain.Containers;
 5 using Skight.eLiteWeb.Presentation.Web.FrontControllers;
 6 
 7 namespace Skight.eLiteWeb.Application.Startup
 8 {
 9     public class ApplicationStartup
10     {
11         public void run()
12         {
13             var registration = create_registration();
14             new RegistrationScanner(registration,
15                                                Assembly.GetAssembly(typeof (Container)),
16                                                Assembly.GetAssembly(typeof (FrontController)),
17                                                Assembly.GetAssembly(typeof (StartupCommand)))
18                                                .run();
19 
20         }
21 
22         private Registration create_registration()
23         {
24             IDictionary<Type, DiscreteItemResolver> item_resolvers = new Dictionary<Type, DiscreteItemResolver>();
25             Container.initialize_with(new ResolverImpl(item_resolvers));
26             return new RegistrationImpl(item_resolvers);
27         }
28     }
29 }

Global.asax系统入口,把所有的代码串起来。


 1 <%@ Application Language="C#" %>
 2 <%@ Import Namespace="Skight.eLiteWeb.Application.Startup" %>
 3 <script  RunAt="server">
 4 
 5     private void Application_Start(object sender, EventArgs e)
 6     {
 7        new ApplicationStartup().run();
 8     }
 9 
10 </script>

原文出自:
http://www.oschina.net/code/snippet_871522_16735

只有注册用户登录后才能发表评论。


网站导航: