Unity依赖注入

什么是IOC

  IOC(Inversion Of Control 控制反转):又被成为依赖注入(DI:Dependence Injection)

  控制反转就是创建对象的的权利有开发人员控制,转到了由容器控制。

  不创建对象,但描述创建他们的方式,代码不直接与对象和服务关联,在配置文件描述某个组件需要那一项服务,由容器把他们关联到一起,

  其中一个重要思想是(别来找我,我回来找你)

  比如A类型中使用B类型,而B的实例类型并不由A来创建,交给容器进行创建和管理,  

 

通过代码和配置文件进行注入

  通过nuget引入Unity

    

  //配置文件的方式需要引入Microsoft.Practices.Unity.dll、Microsoft.Practices.Unity.Configuration.dll

 

  首先创建IProduct接口,Milk、Sugar类继承IProduct

  1、代码注入

 public interface IProduct
    {
        string ClassName { get; set; }

        void show();
    }

   public class Milk:IProduct
    {
        public string ClassName { get; set; }
       

        public void show()
        {
            Console.WriteLine("牛奶:"+ClassName);
        }
    }

   public class Sugar : IProduct
    {
        public string ClassName { get; set; }

        public void show()
        {
            Console.WriteLine("糖:" + ClassName);
        }
    }

 

//注入和获取需要用到同一个容器

using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
//using Unity;

namespace UnityDemo
{
    /// <summary>
    /// 依赖注入
    /// </summary>
    public   class ContainerCode
    {
      static  IUnityContainer unityContainer = new UnityContainer();
        public static void Init()
        {
            //默认方式 无名命
            unityContainer.RegisterType<IProduct, Milk>();

            //命名方式
            unityContainer.RegisterType<IProduct, Sugar>("sugar");
            
        }


        public static void Get()
        {
            //获取无命名方式
           IProduct product= unityContainer.Resolve<IProduct>();
            product.ClassName = product.GetType().Name;
            product.show();

            //命名方式
            IProduct _sugar = unityContainer.Resolve<IProduct>("sugar");
            _sugar.ClassName = _sugar.GetType().Name;
            _sugar.show();
            Console.WriteLine("_________________________________");
            Console.ForegroundColor = ConsoleColor.Blue;
            //获取容器中已注册的已命名对象
            IEnumerable<IProduct> products = unityContainer.ResolveAll<IProduct>();
            foreach (var item in products)
            {
                item.ClassName = item.GetType().Name;
                item.show();
            }

        }

    }
}
View Code

 

2、配置文件注入

  在配置文件App.config或 Web.config中的configuration节点下添加

  其中configSections节点必须放在第一个位置,不然会报错

  配置节点详细图(顺手保存的(^_−)☆)

  

  如下app.config内容:

    

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!--必须放在第一个位置-->
  <configSections>
    
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <aliases>
      <!--定义类型别名-->
      <add alias="Iproduct" type="UnityDemo.IProduct,UnityDemo"></add>
      <add alias="Milk" type="UnityDemo.Milk,UnityDemo"></add>
      <add alias="Sugar1" type="UnityDemo.Sugar,UnityDemo"></add>
    </aliases>
    <!--容器-->
    <container name="MyContainer">
      <!--映射关系,与上面别名对应-->
      <register type="Iproduct" mapTo="Milk"></register><!--无命名方式-->
      <register type="Iproduct" mapTo="Sugar1" name="_Sugar"></register>
    </container>
  </unity>
  
  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

用到的引用

using System.Configuration;

using Microsoft.Practices.Unity;

using Microsoft.Practices.Unity.Configuration;

using System.IO;

  

/// <summary>
        /// 配置文件注入
        /// </summary>
        public static void Config()
        {
            //初始化容器
            IUnityContainer unityContainer = new UnityContainer();

            //获取指定名称的节点
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            //获取设置的容器名
            section.Configure(unityContainer, "MyContainer");

            //  section.Containers.Default.Configure(unityContainer);
            //获取命名为_Sugar
            IProduct product = unityContainer.Resolve<IProduct>("_Sugar");
            product.ClassName = product.GetType().Name;
            product.show();
            //获取默认的
            IProduct product1 = unityContainer.Resolve<IProduct>();
            product1.ClassName = product.GetType().Name;
            product1.show();

        }

 

 

配置文件通过会很大,可以单独放到一个文件中,在根目录创建Unity.config

    

   具体代码

  

 public static void Config1()
        {
            //将单独的config配置放在外面

            IUnityContainer unityContainer = new UnityContainer();
           // string configFile = "Unity.config";

            //获取文件路径,绝对
           string filePath= Path.GetFullPath("../../Unity.config");
            var fileMap = new ExeConfigurationFileMap(filePath);
            fileMap.ExeConfigFilename = "Unity.config";//指定文件名
            //从config读取配置信息
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);


            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection("unity");

            section.Configure(unityContainer, "MyContainer");

            //  section.Containers.Default.Configure(unityContainer);
            IProduct product = unityContainer.Resolve<IProduct>("_Sugar");
            product.ClassName = product.GetType().Name;
            product.show();

            IProduct product1 = unityContainer.Resolve<IProduct>();
            product1.ClassName = product.GetType().Name;
            product1.show();

        }

 

  

使用构造函数(有参)进行注入

  首先把上面容器进行封装一下,添加一个UnityContainerHelp类

  

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Collections.Generic;
using System.Configuration;
using System.IO;

namespace UnityDemo
{
    public class UnityContainerHelp
    {
        private IUnityContainer unityContainer;

        public UnityContainerHelp()
        {
            unityContainer = new UnityContainer();

            //获取文件路径,绝对
            string filePath = Path.GetFullPath("../../Unity.config");
            var fileMap = new ExeConfigurationFileMap(filePath);
            fileMap.ExeConfigFilename = "Unity.config";//指定文件名
            //从config读取配置信息
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection("unity");
            section.Configure(unityContainer, "MyContainer");
        }


        public T GetServer<T>()
        {
            return unityContainer.Resolve<T>();
        }
        /// <summary>
        /// 配置文件的名称
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public T GetServer<T>(string name)
        {
            return unityContainer.Resolve<T>(name);
        }

        public T GetServer<T>(Dictionary<string,object> paramateList)
        {
            var lis = new Microsoft.Practices.Unity.ParameterOverrides();
            foreach (var item in paramateList)
            {
                lis.Add(item.Key, item.Value);
            }
            return unityContainer.Resolve<T>(lis);
        }


    }
}
View Code

 

 

    创建接口和类

     *Unity会默认使用构造函数参数最多的一个进行注入

using System;
using Unity;

namespace UnityDemo
{

    public interface ITest
    {
         String Name { get; set; }
         int Age { get; set; }

        void ShowInfo();


    }

    public class Test : ITest
    {

       
        public Test()
        {

        }
        [InjectionConstructor]
        public Test(string Name,int Age)
        {
            this.Name = Name;
            this.Age = Age;
        }
        public string Name { get ; set ; }
        public int Age { get; set; }

        public void ShowInfo()
        {
            Console.WriteLine("我是构造函数中的name:{0},我是age{1}",this.Name,this.Age);
        }

       
    }
}

 

  修改配置文件

    添加 以下节点

      

   <add alias="ITest" type="UnityDemo.ITest,UnityDemo"></add>
      <add alias="Test" type="UnityDemo.Test,UnityDemo"></add>

  

  <register type="ITest" mapTo="Test" ></register>

 

  Program调用

  需要注意一下:key必须和构造函数参数大小写保持一致

       //构造函数注入
            Dictionary<string, object> parameterList = new Dictionary<string, object>();
            parameterList.Add("Name", "彭于晏");
            parameterList.Add("Age", 18);
           ITest test= unityContainerHelp.GetServer<ITest>(parameterList);
            test.ShowInfo();

 

  

  

  

  

 

  

 

posted @ 2019-09-11 19:39  冷瞳ruin  阅读(554)  评论(0编辑  收藏  举报