對依賴注入( http://www.oschina.net/code/snippet_871522_15682) 的進一步加強.
作為基本功能的注冊,使用語法是:registration.register<Interface,Implementation>().
可以到了實際的項目中,要注冊的接口和類可能不止一個兩個,會成百上千。無論是用C#代碼來注冊,還是用XML文件來配置,都是開發(fā)者的噩夢。
這里,讓我們來個思維的反轉: 變集中配置為分散聲明。
1 為要注冊的類,加入RegisterInContainer的聲明
2 在系統(tǒng)啟動的時候,掃描所有的類,對有RegisterInContainer的類,找到它所有實現(xiàn)的接口,把這些接口和該類綁定注冊。
作為基本功能的注冊,使用語法是:registration.register<Interface,Implementation>().
可以到了實際的項目中,要注冊的接口和類可能不止一個兩個,會成百上千。無論是用C#代碼來注冊,還是用XML文件來配置,都是開發(fā)者的噩夢。
這里,讓我們來個思維的反轉: 變集中配置為分散聲明。
1 為要注冊的類,加入RegisterInContainer的聲明
2 在系統(tǒng)啟動的時候,掃描所有的類,對有RegisterInContainer的類,找到它所有實現(xiàn)的接口,把這些接口和該類綁定注冊。
用于裝飾要注入類的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 { get; set; }
15 public Type type_to_register_in_container { get; set; }
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 }
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 { get; set; }
15 public Type type_to_register_in_container { get; set; }
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參數(shù),指定是否單件方式生成注冊類。
1 namespace Skight.eLiteWeb.Domain.Containers
2 {
3 public enum LifeCycle
4 {
5 single_call,
6 singleton
7 }
8 }
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 }
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添加一個方法:反過來,為一個解析器(實現(xiàn)類)注冊多個接口。
1 void register(DiscreteItemResolver resolver, params Type[] contracts);
2
2
掃描注冊機,在系統(tǒng)啟動時調用一次。
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 }
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 }
系統(tǒng)啟動:創(chuàng)建注冊類,然后傳入必要的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 }
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系統(tǒng)入口,把所有的代碼串起來。
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>
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