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(); } } } }
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); } } }
创建接口和类
*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();