[IoC容器Unity]第三回:依赖注入
上節(jié)介紹了,Unity的Lifetime Managers生命周期,Unity具體實現(xiàn)依賴注入包含構(gòu)造函數(shù)注入、屬性注入、方法注入,所謂注入相當(dāng)賦值,下面一個一個來介紹。
2.構(gòu)造函數(shù)注入
Unity利用Resolve方法解析一個對象,都是調(diào)用注冊類型的構(gòu)造函數(shù)來初始化的,初始化時,Unity能夠控制初始化的值,當(dāng)然,我們要給Unity提供足夠的原料,要不然也是巧婦難無米之炊,下面看一些簡單的示例。
先準(zhǔn)備幾個類如下:
/// <summary>/// 班級接口/// </summary>public interface IClass{string ClassName { get; set; }void ShowInfo();}/// <summary>/// 計科班/// </summary>public class CbClass : IClass{public string ClassName { get; set; }public void ShowInfo(){Console.WriteLine("計科班:{0}", ClassName);}}/// <summary>/// 電商班/// </summary>public class EcClass : IClass{public string ClassName { get; set; }public void ShowInfo(){Console.WriteLine("電商班:{0}", ClassName);}}/// <summary>/// 學(xué)生接口/// </summary>public interface IStudent{string Name { get; set; }//就讀班級void ShowInfo();}/// <summary>/// 學(xué)生/// </summary>public class QlinStudent : IStudent{public string Name { get; set; }private IClass ToClass { get; set; }public QlinStudent(IClass _class){ToClass = _class;}public void ShowInfo(){Console.WriteLine("{0}就讀班級:{1}", Name, ToClass.ClassName);}}是一個班級和學(xué)生的結(jié)構(gòu),現(xiàn)在我們要解析一個學(xué)生IStudent,我們看到具體學(xué)生類QlinStudent的構(gòu)造函數(shù)需要一個班級接口,當(dāng)然要給IUnityContainer容器提供這個班級映射還有學(xué)生自己的映射,就你要什么東東,首先要提供IUnityContainer什么東東。
2.1 默認(rèn)方式
默認(rèn)方式跟new一個對象,它會根據(jù)你提供的材料,選擇一個構(gòu)造函數(shù),即要有構(gòu)造器要能訪問權(quán)限,用Public修飾,構(gòu)造函數(shù)的參數(shù)也要提供,即IClass也要能解析,不然就報錯了,編程注入方式如下:
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認(rèn)注冊(無命名),如果后面還有默認(rèn)注冊會覆蓋前面的container.RegisterType<IClass, CbClass>();container.RegisterType<IStudent, QlinStudent>();//解析默認(rèn)對象IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}配置文件方式 如下:
<?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"><!--引用命名空間--><namespace name="ConsoleApplication1.UnityDemo.Constructor" /><!--引用程序集--><assembly name="ConsoleApplication1" /><!--容器--><container name="FirstClass"><!--映射關(guān)系--><register type="IClass" mapTo="CbClass"></register><register type="IClass" name="ec" mapTo="EcClass"></register><register type="IStudent" mapTo="QlinStudent"></register></container></unity> </configuration>?以下是加載配置文件
public static void ConStructorConfigTest1(){IUnityContainer container = new UnityContainer();string configFile = "http://www.cnblogs.com/UnityDemo/Constructor/Unity.config";var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile };//從config文件中讀取配置信息Configuration configuration =ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);//獲取指定名稱的配置節(jié)UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection("unity");//載入名稱為FirstClass 的container節(jié)點container.LoadConfiguration(section, "FirstClass");IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}?
2.2 指定構(gòu)造函數(shù)
如果構(gòu)造函數(shù)有多個,它也會按照上面那樣來初始化一個對象,我們還可以顯示用InjectionConstructor特性來指定一個構(gòu)造函數(shù)來解析對象,如下聲明:
public class QlinStudent : IStudent{private string Name { get; set; }private IClass ToClass { get; set; }public QlinStudent(){}[InjectionConstructor]public QlinStudent(IClass _class,string name){ToClass = _class;Name = name;}public void ShowInfo(){Console.WriteLine("{0}就讀班級:{1}", Name, ToClass.ClassName);}}?
2.3 指定參數(shù)依賴的注冊名稱
構(gòu)造函數(shù)中IClass參數(shù),如果IUnityContainer注冊了多個,默認(rèn)是使用無名稱的那個注冊,也可以通過Dependency依賴哪個名稱來指定哪個來注冊,代碼,指定ec名稱如下:
[InjectionConstructor]public QlinStudent([Dependency("ec")]IClass _class){ToClass = _class;}下面注冊一個名稱為ec的映射,如果沒有名稱ec的映射將報錯
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認(rèn)注冊(無命名),如果后面還有默認(rèn)注冊會覆蓋前面的container.RegisterType<IClass, CbClass>();//命名注冊container.RegisterType<IClass, EcClass>("ec");container.RegisterType<IStudent, QlinStudent>();//解析默認(rèn)對象IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}配置文件方式,代碼不變,配置中添加一個 name屬性就行,如下:
<container name="FirstClass"><!--映射關(guān)系--><register type="IClass" mapTo="CbClass"></register><register type="IClass" name="ec" mapTo="EcClass"></register><register type="IStudent" mapTo="QlinStudent"></register></container>?
2.4 指定參數(shù)值
構(gòu)造器中的參數(shù)也可以依賴一個指定的類型值,如下代碼依賴于EcClass類型,可以讓構(gòu)造函數(shù)中可以傳入一個具體的類型,這也是構(gòu)造函數(shù)傳參數(shù),如下:
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認(rèn)注冊(無命名),如果后面還有默認(rèn)注冊會覆蓋前面的container.RegisterType<IClass, CbClass>();//命名注冊container.RegisterType<IClass, EcClass>("ec");container.RegisterType<IStudent, QlinStudent>(new InjectionConstructor(new CbClass()));IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}或者注冊一個實例對象,如下:
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();IClass cbClass = new CbClass { ClassName="計科051班" };//實例注冊命名實例container.RegisterInstance<IClass>("ec", cbClass);container.RegisterType<IStudent, QlinStudent>();IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}?
配置文件也可以指定類型依賴,如下,指定EcClass:
<register type="IStudent" mapTo="QlinStudent"><constructor><param name="_class" type="IClass"><dependency type="EcClass"/></param></constructor></register>上面已經(jīng)介紹了傳參數(shù),是用InjectionConstructor類型,現(xiàn)在構(gòu)造函數(shù),多一個參數(shù),如下:
[InjectionConstructor]public QlinStudent([Dependency("ec")]IClass _class, string name){ToClass = _class;Name = name;}多了一個name參數(shù),那必須為容器IUnityContainer提供這個參數(shù),沒有這個原材料,它無法構(gòu)造,就會報錯,如下代碼:
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();container.RegisterType<IStudent, QlinStudent>(new InjectionConstructor(new CbClass() { ClassName = "計科051" }, "Qlin"));IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo(); }注入?yún)?shù)后,也可以下次解析的時候,通過ParameterOverrides類來覆蓋原來的參數(shù),改變參數(shù)值,如下:
public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();container.RegisterType<IStudent, QlinStudent>(new InjectionConstructor(new CbClass() { ClassName = "計科051" }, "Qlin"));IStudent student = container.Resolve<IStudent>();student.ShowInfo();//覆蓋參數(shù)解析IStudent student1 = container.Resolve<IStudent>(new ParameterOverrides(){{"_class",new EcClass(){ ClassName="電商051"}},{"name","linq"}});student1.ShowInfo();}?
3.屬性注入
就是Unity容器解析對象時,為屬性賦值,有操作權(quán)限要Public修飾屬性。屬性注入方式和構(gòu)造函數(shù)注入類似,只需在需要注入的屬性上增加一個Dependency特性,Dependency指定一個注冊名稱name參數(shù)用來指定注入對象的名稱,屬性注入也是伴隨著類型初始化時注入的,在解析時自動注入,所以解析時跟以前一樣。代碼修改如下,在ToClass屬性上增加了Dependency特性,來表示這個屬性需要注入:
public class QlinStudent : IStudent{public string Name { get; set; }[Dependency("ec")]public IClass ToClass { get; set; }public void ShowInfo(){Console.WriteLine("{0}就讀班級:{1}", Name, ToClass.ClassName);}}代碼方式如下:
IUnityContainer container = new UnityContainer();container.RegisterType<IClass, EcClass>("ec"); container.RegisterType<IStudent, QlinStudent>();IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();配置文件方式,依賴的<dependency?name="ec1"?name值 可指定注冊時注冊的名稱:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"><!--引用命名空間--><namespace name="ConsoleApplication1.UnityDemo.Constructor4" /><!--引用程序集--><assembly name="ConsoleApplication1" /><!--容器--><container name="FirstClass"><!--映射關(guān)系--><register type="IClass" mapTo="CbClass"> </register><register type="IClass" name="ec1" mapTo="EcClass"><property name="ClassName" propertyType="System.String" value="電商051" /></register><register type="IStudent" mapTo="QlinStudent"><property name="ToClass"><dependency name="ec1" type="EcClass"/></property></register></container></unity>?
調(diào)用效果圖:
4.方法注入
用public修飾方法,方法注入也是跟構(gòu)造函數(shù)類似代碼修改如下
public class QlinStudent : IStudent{public string Name { get; set; }private IClass ToClass { get; set; }[InjectionMethod]public void InitClass(IClass _class){ToClass = _class;}public void ShowInfo(){Console.WriteLine("{0}就讀班級:{1}", Name, ToClass.ClassName);}}編程方式注入不變,就是初始化時,注入值,如下:
IUnityContainer container = new UnityContainer();container.RegisterType<IClass, EcClass>(); container.RegisterType<IStudent, QlinStudent>();IStudent student = container.Resolve<IStudent>();student.ShowInfo();配置文件方式:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"><!--引用命名空間--><namespace name="ConsoleApplication1.UnityDemo.Constructor5" /><!--引用程序集--><assembly name="ConsoleApplication1" /><!--容器--><container name="FirstClass"><!--映射關(guān)系--><register type="IClass" mapTo="CbClass"> </register><register type="IClass" name="ec1" mapTo="EcClass"><property name="ClassName" propertyType="System.String" value="電商051" /></register><register type="IStudent" mapTo="QlinStudent"><property name="Name" propertyType="System.String" value="Qlin" /><method name="InitClass"><param name="_class" type="IClass"><dependency name="ec1" type="EcClass"/></param></method></register></container></unity>?
5.小結(jié)
?介紹了3種依賴注入方式,平時主要也就用到這么幾種,其它還有復(fù)雜的像擴(kuò)展容器等,通過本節(jié),基本知道Unity的使用了。
轉(zhuǎn)載于:https://www.cnblogs.com/sjqq/p/7492245.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的[IoC容器Unity]第三回:依赖注入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jsp开发入门
- 下一篇: HDU 3966-Aragorn's S