依赖注入的简单实现

依赖注入的简单实现_第1张图片

Container注入框架的进入点

 1  namespace  Skight.LightWeb.Domain
 2  {
 3       public   class  Container
 4      {
 5           private   static  Resolver underlying_resolver;
 6           public   static  Resolver Current
 7          {
 8               get  {  return  underlying_resolver; }
 9          }
10           public   static  T get_a < T > ()
11          {
12               return  underlying_resolver.get_a < T > ();
13          }
14 
15           public   static   void  initialize_with(Resolver resolver)
16          {
17              underlying_resolver  =  resolver;
18          }
19      }
20  }

Container的实现核心,依赖解析器的接口定义。(接口名称,我不加I,故意的)


 1  using  System;
 2 
 3  namespace  Skight.LightWeb.Domain
 4  {
 5       public   interface  Resolver
 6      {
 7          Dependency get_a < Dependency > ();
 8           object  get_a(Type type);
 9      }
10  }

依赖解析器的测试 (使用Machine Specification)


 1  using  System;
 2  using  System.Collections.Generic;
 3  using  Machine.Specifications;
 4  using  Rhino.Mocks;
 5 
 6  namespace  Skight.LightWeb.Domain.Specs
 7  {
 8       public   class  When_bind_a_class_to_a_intefercate
 9      {
10           private  Establish context  =
11              ()  =>
12                  {
13                      var item_resolver  =  MockRepository.GenerateMock < DiscreteItemResolver > ();
14                      var dictioary  =   new  Dictionary < Type, DiscreteItemResolver > ();
15                      dictioary.Add( typeof  (MockInterface), item_resolver);
16                      subject  =   new  ResolverImpl(dictioary);
17                      item_resolver.Stub(x  =>  x.resolve()).Return( new  MockImplementaion());
18                  };
19 
20          private  It should_resolve_the_interface_to_the_class  =
21              ()  =>  subject.get_a < MockInterface > ().ShouldBeOfType < MockImplementaion > ();
22 
23           private   static  ResolverImpl subject;
24           private   interface  MockInterface { }
25           private   class  MockImplementaion : MockInterface { }
26          
27      }   
28  }

解构器的实现


 1  using  System;
 2  using  System.Collections.Generic;
 3 
 4  namespace  Skight.LightWeb.Domain
 5  {
 6       public   class  ResolverImpl:Resolver
 7      {
 8           private   readonly  IDictionary < Type, DiscreteItemResolver >  item_resolvers;
 9 
10           public  ResolverImpl(IDictionary < Type, DiscreteItemResolver >  itemResolvers)
11          {
12              item_resolvers  =  itemResolvers;
13          }
14 
15           public  Dependency get_a < Dependency > ()
16          {
17               return  (Dependency) item_resolvers[ typeof  (Dependency)].resolve();
18          }
19 
20           public   object  get_a(Type type)
21          {
22               return  item_resolvers[type].resolve();
23          }
24      }
25  }

注册器的接口定义 (是的,先要注册才能解析,可是业务视图却是反的)


1  namespace  Skight.LightWeb.Domain
2  {
3       public   interface  Registration
4      {
5           void  register < Contract, Implementaion > () where Implementaion : Contract;
6      }
7  }

注册器的的测试


 1  using  System;
 2  using  System.Collections.Generic;
 3  using  Machine.Specifications;
 4 
 5  namespace  Skight.LightWeb.Domain.Specs
 6  {
 7       public   class  When_use_Registration_to_register_an_infterface_to_a_class
 8      {
 9           private  Establish context  =
10              ()  =>
11                  {
12                      resolver_dictionary  =   new  Dictionary < Type, DiscreteItemResolver > ();
13                      subject  =   new  RegistrationImpl(resolver_dictionary);
14                      
15              };
16 
17           private  Because of  =
18              ()  =>  subject.register < MockInterface, MockImplementation > ();
19 
20           private  It the_key_value_pair_should_be_added_to_resovler_dictionary  =
21              ()  =>  resolver_dictionary[ typeof  (MockInterface)].resolve().ShouldBeOfType < MockImplementation > ();
22          
23           private   static  RegistrationImpl subject;
24           private   static  Dictionary < Type, DiscreteItemResolver >  resolver_dictionary;
25 
26           private   interface  MockInterface{}
27           private   class  MockImplementation:MockInterface {}
28      }
29  }

注册器的的实现

 1  using  System;
 2  using  System.Collections.Generic;
 3 
 4  namespace  Skight.LightWeb.Domain
 5  {
 6       public   class  RegistrationImpl:Registration
 7      {
 8           private  IDictionary < Type, DiscreteItemResolver >  item_resolvers;
 9           public  RegistrationImpl(IDictionary < Type, DiscreteItemResolver >  item_resolvers)
10          {
11               this .item_resolvers  =  item_resolvers;
12          }
13 
14           public   void  register < Contract, Implementation > () where Implementation : Contract
15          {
16             
17              item_resolvers.Add( typeof (Contract),  new  TypeResolver( typeof (Implementation)));
18          }
19      }
20 
21  }

具体解构器接口定义 (命名:离散解构器,可以看作是对象工厂的一种形式)


1  namespace  Skight.LightWeb.Domain
2  {
3       public   interface  DiscreteItemResolver
4      {
5           object  resolve();
6      }
7  }

离散解构器的测试


 1  using  System;
 2  using  Machine.Specifications;
 3  using  Rhino.Mocks;
 4 
 5  namespace  Skight.LightWeb.Domain.Specs
 6  {
 7       public   class  TypeResolverSpecs
 8      {
 9           protected   static  TypeResolver subject;
10      }
11 
12       public   class  given_a_simple_type_which_has_a_parameterless_constructor
13          : TypeResolverSpecs
14      {
15           private  Establish context  =
16              ()  =>  subject  =   new  TypeResolver( typeof  (SimpleType));
17 
18           private  It should_create_object_from_class  =
19              ()  =>  subject.resolve().ShouldBeOfType < SimpleType > ();
20 
21           protected   class  SimpleType{}
22      }
23 
24       public   class  given_a_complex_type_whose_constructor_need_other_types
25         : TypeResolverSpecs {
26           private  Establish context  =
27              ()  =>
28                  {
29                      var resolver  =  MockRepository.GenerateMock < Resolver > ();
30                      Container.initialize_with(resolver);
31                      resolver.Stub(x  =>  x.get_a(Arg < Type > .Is.Equal( typeof  (SimpleType))))
32                          .Return( new  SimpleType());
33 
34                      subject  =   new  TypeResolver( typeof  (ComplexType));
35              };
36 
37           private  It should_create_object_from_class  =
38              ()  =>  subject.resolve().ShouldBeOfType < ComplexType > ();
39 
40           protected   class  SimpleType{}
41           protected   class  ComplexType
42          {
43               private  SimpleType simple;
44 
45               public  ComplexType(SimpleType simple)
46              {
47                   this .simple  =  simple;
48              }
49          }
50      }
51  }

离散解构器的实现 (有递归,如果该类构造器有接口参数的,需要用Container解构)


 1  using  System;
 2  using  System.Collections.Generic;
 3  using  System.Linq;
 4  using  System.Reflection;
 5 
 6  namespace  Skight.LightWeb.Domain
 7  {
 8       public   class  TypeResolver:DiscreteItemResolver
 9      {
10           private   readonly  Type type_to_create;
11 
12           public  TypeResolver(Type type_to_create)
13          {
14               this .type_to_create  =  type_to_create;
15          }
16 
17           public   object  resolve()
18          {
19              ParameterInfo[] param_types  =  get_constructor_parameters();
20              IEnumerable < object >  parameters  =  get_parameters(param_types);
21               return  Activator.CreateInstance(type_to_create, parameters.ToArray());
22          }
23 
24           private  IEnumerable < object >  get_parameters(ParameterInfo[] param_types)
25          {
26               return  param_types.Select(x  =>  Container.Current.get_a(x.ParameterType));
27          }
28 
29           private  ParameterInfo[] get_constructor_parameters()
30          {
31              var constructor =  type_to_create.GetConstructors()
32                  .OrderByDescending(x  =>  x.GetParameters().Count())
33                  .First();
34               return  constructor.GetParameters();
35          }
36      }
37  }

集成测试,完整的用例。


 1  using  System;
 2  using  System.Collections.Generic;
 3  using  Machine.Specifications;
 4 
 5  namespace  Skight.LightWeb.Domain.Specs
 6  {
 7       public   class  DependencyIntegrationSpecs
 8      {
 9           private  Establish context  =
10              ()  =>
11                  {
12                      IDictionary < Type, DiscreteItemResolver >  item_resolvers  =   new  Dictionary < Type, DiscreteItemResolver > ();
13                      registration  =   new  RegistrationImpl(item_resolvers);
14                      Container.initialize_with( new  ResolverImpl(item_resolvers));
15                      
16                  };
17 
18           protected   static  Registration registration;
19      }
20 
21       public   class  when_registry_a_simple_class_RepositoryImpl_without_further_dependency:DependencyIntegrationSpecs
22      {
23           private  Establish context  =
24              ()  =>  registration.register < Repository, RepositoryImpl > ();
25           private  Because of  =
26             ()  =>  result  =  Container.get_a < Repository > ();
27 
28           private  It should_get_a_object_which_is_not_null  =
29              ()  =>  result.ShouldNotBeNull();
30 
31           private  It should_get_RepositoryImpl_class  =
32              ()  =>  result.ShouldBeOfType < RepositoryImpl > ();
33 
34           private   static  Repository result;
35      }
36 
37       public   class  when_registry_a_class_ServiceImpl_which_depend_on_another_interface_Repository : DependencyIntegrationSpecs {
38           private  Establish context  =
39              ()  =>  {
40                  registration.register < Repository, RepositoryImpl > ();
41                  registration.register < Service,ServiceImpl > ();
42              };
43           private  Because of  =
44             ()  =>  result  =  Container.get_a < Service > ();
45 
46           private  It inject_repository_should_not_be_null  =
47              ()  =>  result.ShouldNotBeNull();
48 
49           private  It should_inject_service  =
50              ()  =>  result.ShouldBeOfType < ServiceImpl > ();
51 
52           private  It should_inject_repository_into_service  =
53              ()  =>  result.Repository.ShouldBeOfType < RepositoryImpl > ();
54          
55 
56           private   static  Service result;
57      }
58       public   interface  Repository { }
59       public   class  RepositoryImpl : Repository { }
60       public   interface  Service{Repository Repository {  get ; } }
61       public   class  ServiceImpl : Service
62      {
63           private  Repository repository;
64 
65           public  ServiceImpl(Repository repository)
66          {
67               this .repository  =  repository;
68          }
69 
70           public  Repository Repository
71          {
72               get  {  return  repository; }
73          }
74      }
75  }

Bootstrapper系鞋带代码,把所有的碎片组合起来,作为Web,在Gloable.asax中调用


 1  using  System;
 2  using  System.Collections.Generic;
 3  using  Skight.LightWeb.Domain;
 4  using  Skight.LightWeb.Presentation.Web.FrontController;
 5 
 6 
 7  namespace  Skight.LightWeb.Application.Startup
 8  {
 9       public   class  ApplicationStartup
10      {
11           public   void  run()
12          {
13              IDictionary < Type, DiscreteItemResolver >  item_resolvers  =   new  Dictionary < Type, DiscreteItemResolver > ();
14              Container.initialize_with( new  ResolverImpl(item_resolvers));
15              var registration  =   new  RegistrationImpl(item_resolvers);
16              registration.register < Repository,RepositoryImpl > ();
17              registration.register < FrontController,FrontControllerImpl > ();
18              registration.register < CommandResolver,CommandResolverImpl > ();
19              
20          }
21 
22           ///   <summary>
23           ///  Test purpose class an interface
24           ///   </summary>
25           public   interface  Repository { }
26           public   class  RepositoryImpl : Repository { }
27      }
28  }

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






你可能感兴趣的:(依赖注入的简单实现)