Unity框架的依賴注入-Dependency injection


一、構造注入 Constructors injection

構造注入適用於對象強依賴的情況,需要在構造函數中實例化別外一個類型,以控制對象的實例化順序。已經存在的實例是不能使用構造注入,即不能使用構造注入改變實例屬性。

以下情況適合使用構造注入

  • 在實例化父對象時自動實例化子對象
  • 想用一個簡單的方法表示代碼是類的依賴關系
  • 父對象有能在太多的構造函數
  • 父對象的構造函數不能有太多的參數
  • 需要隱藏對象內部字段的值,而用屬性或方法會使其顯露
  • 要控制父對象依賴的子對象,需要將依賴從代碼中移出時

Unity建議當不確定使用哪種注入時,使用構造注入,除非是要在一個已有的對象實例改變屬性時才使用其它注入。

DEMO:

namespace ConsoleUnityDemo.ConstractrInjection
{
    public class Parent
    {
        private SubClass subClass;
        public Parent(SubClass subInstance)
        {
            subClass = subInstance;
        }
 
        public string SubClassName
        {
            get {return subClass.ClassName;}
        }
    }
 
    public class SubClass
    {
        public string ClassName{get;set;}
    }
 
    public class SubClassConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;
            return base.CanConvertFrom(context, sourceType);
        }
 
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            return base.ConvertTo(context, culture, value, destinationType);
        }
 
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                SubClass model = new SubClass();
                model.ClassName = value.ToString();
                return model;
            }
            return base.ConvertFrom(context, culture, value);
        }
    }
 
    class Program
    {
 
        static void Main(string[] args)
        {
            UnityConfigurationSection unitySection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            UnityContainer unityContainer = new UnityContainer();
            unitySection.Configure(unityContainer, "ConstractInject"); //獲取容器
            ConstractrInjection.Parent parent = unityContainer.Resolve<ConstractrInjection.Parent>("ParentClass");  //取實例
 
            Console.WriteLine(string.Format(parent.SubClassName));
        }
    }
}

Unity配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="Parent" type="ConsoleUnityDemo.ConstractrInjection.Parent, ConsoleUnityDemo" />
    <alias alias="SubClass" type="ConsoleUnityDemo.ConstractrInjection.SubClass, ConsoleUnityDemo" />
    <alias alias="SubClassConverter" type="ConsoleUnityDemo.ConstractrInjection.SubClassConverter, ConsoleUnityDemo" />
    <container name="ConstractInject">
      <register type="Parent" name="ParentClass" mapTo ="Parent">
        <constructor>
          <param name="subInstance">
            <value value="This is SubClass" typeConverter="SubClassConverter"/>
          </param>
        </constructor>
      </register>
    </container>
  </unity>
  <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
<appSettings>
</appSettings>
</configuration>

 

構造注入存在以下三種情況

  • 單個構造函數時自動注入

當對象只有一個構造函數,Unity會自動實例化構造函數參數所依賴的對象,參數必需是個實體類,不能為接口或抽象類。如

public class BoxA
{
   public BoxA(BoxB box)
  {
  }
}

使用Unity注入時會自動實例化BoxB,在上面的Demo中可以不使用<constructor>節點

  • 當參數為抽象類或接口時,可以用[Dependency("objectName")]來指定所依賴的對象,Unity在構造MyObject對象時會自動將參數映射到DataServices對象
public class MyObject
{
  public MyObject([Dependency("DataService")] IMyService myDataService)
  { 
    // work with the service here
  }
} 
  • 當有多個構造函數,且構造函數的參數個數一樣時,使用InjectionConstructor屬性指定Unity默認調用的構造函數。Unity對實例化對象時會自動調用標記為InjectionConstructor的構造函數
public class MyObject
{

  public MyObject(SomeOtherClass myObjA)
  { 
    ...
  }

  [InjectionConstructor]
  public MyObject(MyDependentClass myObjB)
  { 
    ...
  }

} 

二、屬性注入Sitter injection

屬性注入通入對象公開的屬性改變對象的值,比如記錄日志時常用的方式,ILogger抽象了日志實體,再根據需要實例化不同的日志實體

public class LogManager
{
    ILogger logInstance;
    [Dependency]
    public ILoger
    {
        get{return logInstance;}
        set{logInstance= value;}
    }
    public void WriteLog()
    {
        logInstance.WriteLog();
    }
}
 
用Dependency屬性向Unity暴露這是一個依賴注入的屬性。

屬性注入注意時應該始終在要依賴注入的屬性上加上Dependency 標簽。(我發現好像不加也是可以用的-_-)

三、方法注入Method Call Injection

屬性注入時必需要將對象內部的字段對外公開,但某些時候為了封裝原則,不想對外公開這些屬性時,可以用方法注入。如用Initialize方法代碼Set屬性

public class LogManager
{
    ILogger logInstance;
    
  [InjectionMethod]
    public void Initialize(ILogger instance)
    {
        logInstance = instance
    }
    public void WriteLog()
    {
        logInstance.WriteLog();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM