[IoC容器Unity]第三回:依賴注入

上節介紹了,Unity的Lifetime Managers生命周期,Unity具體實現依賴注入包含構造函數注入、屬性注入、方法注入,所謂注入相當賦值,下面一個一個來介紹。

2.構造函數注入

Unity利用Resolve方法解析一個對象,都是調用注冊類型的構造函數來初始化的,初始化時,Unity能夠控制初始化的值,當然,我們要給Unity提供足夠的原料,要不然也是巧婦難無米之炊,下面看一些簡單的示例。

先準備幾個類如下:

復制代碼
    /// <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>/// 學生接口/// </summary>public interface IStudent{string Name { get; set; }//就讀班級void ShowInfo();}/// <summary>/// 學生/// </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);}}
復制代碼

是一個班級和學生的結構,現在我們要解析一個學生IStudent,我們看到具體學生類QlinStudent的構造函數需要一個班級接口,當然要給IUnityContainer容器提供這個班級映射還有學生自己的映射,就你要什么東東,首先要提供IUnityContainer什么東東。

2.1 默認方式

默認方式跟new一個對象,它會根據你提供的材料,選擇一個構造函數,即要有構造器要能訪問權限,用Public修飾,構造函數的參數也要提供,即IClass也要能解析,不然就報錯了,編程注入方式如下:

復制代碼
        public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認注冊(無命名),如果后面還有默認注冊會覆蓋前面的container.RegisterType<IClass, CbClass>();container.RegisterType<IStudent, QlinStudent>();//解析默認對象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"><!--映射關系--><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);//獲取指定名稱的配置節UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection("unity");//載入名稱為FirstClass 的container節點container.LoadConfiguration(section, "FirstClass");IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}
復制代碼

?

2.2 指定構造函數

如果構造函數有多個,它也會按照上面那樣來初始化一個對象,我們還可以顯示用InjectionConstructor特性來指定一個構造函數來解析對象,如下聲明:

復制代碼
    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 指定參數依賴的注冊名稱

構造函數中IClass參數,如果IUnityContainer注冊了多個,默認是使用無名稱的那個注冊,也可以通過Dependency依賴哪個名稱來指定哪個來注冊,代碼,指定ec名稱如下:

        [InjectionConstructor]public QlinStudent([Dependency("ec")]IClass _class){ToClass = _class;}

下面注冊一個名稱為ec的映射,如果沒有名稱ec的映射將報錯

復制代碼
        public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認注冊(無命名),如果后面還有默認注冊會覆蓋前面的container.RegisterType<IClass, CbClass>();//命名注冊container.RegisterType<IClass, EcClass>("ec");container.RegisterType<IStudent, QlinStudent>();//解析默認對象IStudent splitClass = container.Resolve<IStudent>();splitClass.ShowInfo();}
復制代碼

配置文件方式,代碼不變,配置中添加一個 name屬性就行,如下:

復制代碼
    <container name="FirstClass"><!--映射關系--><register type="IClass"  mapTo="CbClass"></register><register type="IClass" name="ec" mapTo="EcClass"></register><register type="IStudent"  mapTo="QlinStudent"></register></container>
復制代碼

?

2.4 指定參數值

構造器中的參數也可以依賴一個指定的類型值,如下代碼依賴于EcClass類型,可以讓構造函數中可以傳入一個具體的類型,這也是構造函數傳參數,如下:

復制代碼
        public static void ConStructorCodeTest1(){IUnityContainer container = new UnityContainer();//默認注冊(無命名),如果后面還有默認注冊會覆蓋前面的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>
復制代碼

上面已經介紹了傳參數,是用InjectionConstructor類型,現在構造函數,多一個參數,如下:

        [InjectionConstructor]public QlinStudent([Dependency("ec")]IClass _class, string name){ToClass = _class;Name = name;}

多了一個name參數,那必須為容器IUnityContainer提供這個參數,沒有這個原材料,它無法構造,就會報錯,如下代碼:

復制代碼
        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();           }
復制代碼

注入參數后,也可以下次解析的時候,通過ParameterOverrides類來覆蓋原來的參數,改變參數值,如下:

復制代碼
        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();//覆蓋參數解析IStudent student1 = container.Resolve<IStudent>(new ParameterOverrides(){{"_class",new EcClass(){ ClassName="電商051"}},{"name","linq"}});student1.ShowInfo();}
復制代碼

?

3.屬性注入

就是Unity容器解析對象時,為屬性賦值,有操作權限要Public修飾屬性。屬性注入方式和構造函數注入類似,只需在需要注入的屬性上增加一個Dependency特性,Dependency指定一個注冊名稱name參數用來指定注入對象的名稱,屬性注入也是伴隨著類型初始化時注入的,在解析時自動注入,所以解析時跟以前一樣。代碼修改如下,在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"><!--映射關系--><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>
復制代碼

?

調用效果圖:

4.方法注入

用public修飾方法,方法注入也是跟構造函數類似代碼修改如下

復制代碼
    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"><!--映射關系--><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.小結

?介紹了3種依賴注入方式,平時主要也就用到這么幾種,其它還有復雜的像擴展容器等,通過本節,基本知道Unity的使用了。

轉載于:https://www.cnblogs.com/sjqq/p/7492245.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251888.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Apache CarbonData 1.5.0編譯及安裝

2019獨角獸企業重金招聘Python工程師標準>>> 一、編譯環境描述 OpenStack創建五個虛擬機&#xff0c;其中1個主節點&#xff08;hostname為bigdatamaster&#xff09;&#xff0c;4個從節點&#xff08;hostname分別為&#xff0c;bigdataslave1、bigdataslave2、bi…

JS控制網頁全屏

在谷歌&#xff0c;IE等瀏覽器中&#xff0c;點擊F11按鍵會進入網頁全屏模式&#xff0c;如同看電影的劇場模式&#xff0c;這個在代碼中可以通過JS來實現&#xff0c;簡單說下在實現這個需求后的個人總結&#xff1a; 底層網頁是已經加載完畢的&#xff0c;這時我們需要的全屏…

HDU 3966-Aragorn's Story 樹鏈剖分+樹狀數組

題目鏈接 題意&#xff1a;有一棵樹&#xff0c;每個節點有權值 有三種操作&#xff1a; I c1 c2 k 從節點c1到節點c2的路徑上每個節點權值增加kD c1 c2 k 從節點c1到節點c2的路徑上每個節點權值減少kQ i 查詢節點i的權值是多少思路&#xff1a; 樹鏈剖分處理出來的鏈放在數組中…

Filter介紹

Filter 可認為是 Servlet的一種 “ 加強版 ”&#xff0c;它主要用于對用戶請求進行預處理&#xff0c; 也可以對HttpServletResponse 進行后處理&#xff0c;是個典型的處理鏈。Filter 也可對用戶請求生成響應&#xff0c;這一 點與Servlet 相同&#xff0c; 但實際上很少會使…

LeetCode算法題-Jewels and Stones(Java實現)

這是悅樂書的第313次更新&#xff0c;第334篇原創 01 看題和準備 今天介紹的是LeetCode算法題中Easy級別的第182題&#xff08;順位題號是771&#xff09;。字符串J代表珠寶&#xff0c;S代表你擁有的石頭。S中的每個字符都是你擁有的一種石頭。計算S中有多少石頭也是珠寶。J中…

python --- 二分查找算法

二分查找法&#xff1a;在我的理解中這個查找方法為什么會叫二分呢&#xff0c;我認為是將要查詢的一個列表分成了兩份&#xff0c;然后在利用某個值來進行比較&#xff0c;在一個不斷循環的過程中來找出我們要找的某一個值。 廢話不多說&#xff0c;先上代碼&#xff1a; 1 de…

面試題

1. block 的作用由來&#xff0c;跟delegate的區別。 2. swift 的枚舉。 3. iOS保存一個對象。轉載于:https://www.cnblogs.com/studyNT/p/7499779.html

ssm框架下文件上傳

springmvc實現文件上傳的步驟&#xff1a; 1.頁面上&#xff0c;通過input來準備file組件&#xff0c;該標簽&#xff0c;必須給定name屬性值 同時&#xff0c;要求form表單必須給定一個屬性&#xff1a;enctype"multipart/form-data" 2.在pom.xml文件中&#xff0c;…

MySQL via EF6 的試用報告

MySQL via EF6 的試用報告1、如何通過 EF6 來連接 MySQL&#xff1f;2、如何通過 EF6 來實現 CRUD&#xff1f;2.1、Create 添加2.2、Retrieve 查詢2.3、Update 修改2.4、Delete 刪除3、如何更好的運用 EF6 來完成工作&#xff1f;3.1、傳說中 EF 的三種模式3.2、EF6 執行原生 …

Java暑假作業

一.《大護法》觀影有感 ... 從預告開始就期待著這部影片&#xff0c;在看過一遍后又忍不住二刷&#xff0c;影片觀看至第二遍后&#xff0c;對于全片的脈絡也更清晰了一點&#xff0c;雖然打著暴力美學的旗子&#xff0c;但《大護法》偏偏更文藝一些。文藝片是沒有對錯的&a…

使用EasyNetQ組件操作RabbitMQ消息隊列服務

RabbitMQ是一個由erlang開發的AMQP(Advanved Message Queue)的開源實現&#xff0c;是實現消息隊列應用的一個中間件&#xff0c;消息隊列中間件是分布式系統中重要的組件&#xff0c;主要解決應用耦合&#xff0c;異步消息&#xff0c;流量削鋒等問題。實現高性能&#xff0c;…

context-param和init-param的區別

http://www.cnblogs.com/hzj-/articles/1689836.html 轉載于:https://www.cnblogs.com/wangc04/p/7501054.html

TensorFlow 1.12.2 發布,修復 GIF 構造安全漏洞

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; TensorFlow 1.12.2 發布了&#xff0c;此處本修復了一個潛在的安全漏洞&#xff1a; 精心設計的 GIF 圖像可以在解碼過程中產生空指針解引用更新說明&#xff1a; https://github.com/tensorflo…

【教程】如何在標簽打印工具TFORMer Designer中自定義布局?

TEC-IT的在線標簽生成器TFORMer Designer提供標簽打印服務&#xff0c;并提供即用型行業標簽模板作為Web服務。使用此軟件&#xff0c;您可以在幾秒鐘內創建您自己的標簽和表格或在工業和物流業中使用即時可用的模板。TFORMer Designer的最新更新現在允許使用自定義標簽布局。 …

對象變為指定格式的數組

拿到的對象的格式&#xff08;一個對象里面都好多屬性&#xff09; 想要轉換成的數據格式&#xff08;一個數組里面有好多個對象&#xff0c;每個對象有一個id和name的屬性&#xff09; 如何處理的 selectionChange(val) { // 列表選擇var dynamicTags1 [];var arr[]for(var i…

bootstrapValidator remote 驗證問題

1 加載jQuery和bootstrap.min.js 后引入bootstrapValidator.min.js字段驗證之remote 遠程驗證(類似ajax驗證)&#xff0c;返回值必須是 {"valid":true}{"valid":false} true表示 驗證通過 false 表示驗證不通過。 當添加remote 驗證后&#xff0c;驗證通過…

世界頂級的程序員們告訴你:這些書都是你應該讀的

在很早之前就想整理一份來自經驗豐富的頂級程序員推薦閱讀的書籍清單&#xff0c;全棧工程師Dmitry Shvetsov整理了Bob叔以及Jeff Atwood and DHH等世界知名程序員曾經在博客中推薦過的書單&#xff0c;下面我們就一起來看看深受大神們青睞的書籍都是哪些?世界頂級的程序員們告…

《20170911-構建之法:現代軟件工程-閱讀筆記》

第一章&#xff1a; 介紹軟件工程和軟件的關系&#xff0c;軟件程序軟件工程。 軟件工程是把系統的、有序的、可量化的方法應用到軟件的開發、運營和維護上的過程。 計算機科學這一學術領域可以分為以下這些偏理論的領域&#xff1a; 1.計算機理論 2.信息和編碼理論 3.算法和數…

mysql學習(2)索引的本質

2019獨角獸企業重金招聘Python工程師標準>>> 問題&#xff1a;SQL查詢慢怎么辦&#xff1f; 優化手段&#xff0c;加索引。 索引是幫助MYSQL高效的獲取數據的排好序的數據結構。 問題&#xff1a;索引結構為什么使用Btree而不使用二叉樹&#xff0c;紅黑樹或者HASH結…

bzoj4245: [ONTAK2015]OR-XOR

一道很有意思的題目。 先求一次前綴和&#xff0c;可以發現答案是 (sum[0] xor sum[x1])or(sum[x1] xor sum[x2])or(sum[x2] xor sum[x3])or……or(sum[m-1] xor sum[n]) 然后其實&#xff08;a xor b&#xff09;or b a or b 那么sum[0]0,可以把柿子變成 sum[x1] or sum[x2] o…