0%

一、构造注入 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配置

构造注入存在以下三种情况 - 单个构造函数时自动注入 > 当对象只有一个构造函数,Unity会自动实例化构造函数参数所依赖的对象,参数必需是个实体类,不能为接口或抽象类。如 > > public class BoxA > { > public BoxA(BoxB box) > { > } > } > > 使用Unity注入时会自动实例化BoxB,在上面的Demo中可以不使用节点 - 当参数为抽象类或接口时,可以用\[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(); } }