理解依赖注入(IOC)和学习Unity

理解依赖注入(IOC)和学习Unity

Martin Fowler在那篇著名的文章《Inversion of Control Containers and the Dependency Injection pattern》中将具体依赖注入划分为三种形式,即构造器注入、属性(设置)注入和接口注入,习惯将其划分为一种(类型)匹配和三种注入:

  • 类型匹配(Type Matching):虽然我们通过接口(或者抽象类)来进行服务调用,但是服务本身还是实现在某个具体的服务类型中,这就需要某个类型注册机制来解决服务接口和服务类型之间的匹配关系;
  • 构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前解析注册的依赖关系并自行获得相应参数对象;
  • 属性注入(Property Injection):如果需要使用到被依赖对象的某个属性,在被依赖对象被创建之后,IoC容器会自动初始化该属性;
  • 方法注入(Method Injection):如果被依赖对象需要调用某个方法进行相应的初始化,在该对象创建之后,IoC容器会自动调用该方法。

我们创建一个控制台程序,定义如下几个接口(IA、IB、IC和ID)和它们各自的实现类(A、B、C、D)。在类型A中定义了3个属性B、C和D,其类型分别为接口IB、IC和ID。其中属性B在构在函数中被初始化,以为着它会以构造器注入的方式被初始化;属性C上应用了DependencyAttribute特性,意味着这是一个需要以属性注入方式被初始化的依赖属性;属性D则通过方法Initialize初始化,该方法上应用了特性InjectionMethodAttribute,意味着这是一个注入方法在A对象被IoC容器创建的时候会被自动调用。

[csharp] view plaincopy
 
  1. public interface IA { }  
  2.     public interface IB { }  
  3.     public interface IC { }  
  4.     public interface ID { }  
  5.   
  6.     public class A : IA  
  7.     {  
  8.         public IB B { get; set; }  
  9.         [Dependency]  
  10.         public IC C { get; set; }  
  11.         public ID D { get; set; }  
  12.   
  13.         public A(IB b)  
  14.         {  
  15.             this.B = b;  
  16.         }  
  17.         [InjectionMethod]  
  18.         public void Initalize(ID d)  
  19.         {  
  20.             this.D = d;  
  21.         }  
  22.     }  
  23.     public class B : IB { }  
  24.     public class C : IC { }  
  25.     public class D : ID { }  


然后我们为该应用添加一个配置文件,并定义如下一段关于Unity的配置。这段配置定义了一个名称为defaultContainer的Unity容器,并在其中完成了上面定义的接口和对应实现类之间映射的类型匹配。

[html] view plaincopy
 
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <configuration>  
  3.   <configSections>  
  4.     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>  
  5.   </configSections>  
  6.   <unity>  
  7.     <containers>  
  8.       <container name="defaultContainer">  
  9.         <register type="UnityDemo.IA,UnityDemo" mapTo="UnityDemo.A, UnityDemo"/>  
  10.         <register type="UnityDemo.IB,UnityDemo" mapTo="UnityDemo.B, UnityDemo"/>  
  11.         <register type="UnityDemo.IC,UnityDemo" mapTo="UnityDemo.C, UnityDemo"/>  
  12.         <register type="UnityDemo.ID,UnityDemo" mapTo="UnityDemo.D, UnityDemo"/>  
  13.       </container>  
  14.     </containers>  
  15.   </unity>  
  16. </configuration>  


最后在Main方法中创建一个代表IoC容器的UnityContainer对象,并加载配置信息对其进行初始化。然后调用它的泛型的Resolve方法创建一个实现了泛型接口IA的对象。最后将返回对象转变成类型A,并检验其B、C和D属性是否是空

[csharp] view plaincopy
 
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             UnityContainer container = new UnityContainer();  
  6.             UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;  
  7.             configuration.Configure(container, "defaultContainer");  
  8.             A a = container.Resolve<IA>() as A;  
  9.             if (null!=a)  
  10.             {  
  11.                 Console.WriteLine("a.B==null?{0}",a.B==null?"Yes":"No");  
  12.                 Console.WriteLine("a.C==null?{0}", a.C == null ? "Yes" : "No");  
  13.                 Console.WriteLine("a.D==null?{0}", a.D == null ? "Yes" : "No");  
  14.             }  
  15.         }  
  16.     }  


从如下给出的执行结果我们可以得到这样的结论:通过Resolve<IA>方法返回的是一个类型为A的对象,该对象的三个属性被进行了有效的初始化。这个简单的程序分别体现了接口注入(通过相应的接口根据配置解析出相应的实现类型)、构造器注入(属性B)、属性注入(属性C)和方法注入(属性D)

  a.B == null ? No
 a.C == null ? No
 a.D == null ? No
原文地址:https://www.cnblogs.com/a2502971/p/7738035.html