上一篇《我在項目中運用 IOC(依賴注入)--入門篇》只是簡單的使用 IOC。實際項目使用 IOC 的情景複雜多了,好比說,構造函數有多個參數,有多個類繼承同一個接口... Unity都有解決方法。首先回顧一下入門篇的項目需求:項目中數據統計功能,它下面有三種不一樣的統計類型,須要與數據庫交互,而後展現到頁面,在這篇中咱們接着這個需求繼續擴充。html
【沒有接口】數據庫
新增Model 層,LoginUser 當前登陸人。無接口的怎樣用IOC 建立對象。代碼以下ide
Model.LoginUser loginUser = container.Resolve<Model.LoginUser>();
【多個子類】函數
DAL 層 新增ShowResult2 方法學習
public class Analyse:IDAL.IAnalyse { public void ShowResult() { Console.WriteLine("分析底層數據庫交互"); } public void ShowResult2() { Console.WriteLine("這是B類分析底層數據庫交互"); } }
BLL層 新增 AnalyseB ,繼承 IAnalysethis
public class AnalyseB:IBLL.IAnalyse { ////使用依賴注入 [Dependency] public IDAL.IAnalyse dal { get; set; } public void ShowResult() { dal.ShowResult2(); } }
按照入門篇的步驟,須要在core 層 DependencyRegister 修改 DependencyRegisterContainer 方法spa
public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>(); return container; }
咱們發現IBLL.IAnalyse被兩個類繼承,因此在 IOC 容器中注入了兩次。這樣寫能區分開嗎?咱們先在UI 層增長顯示代碼code
/// <summary> /// 多個類繼承同一個接口 /// </summary> private static void IOCMethod4() { IUnityContainer container = DependencyRegister.DependencyRegisterContainer(); IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>(); bll.ShowResult(); }
運行程序,發現每次只會出現 AnalyseB 類的結果。即 IAnalyse=最後註冊的類型 。Unity 的 RegisterType 方法有個參數string name。用key來區分子類型。修改代碼htm
//core 層 public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B"); return container; } //// UI 層 private static void IOCMethod4() { IUnityContainer container = DependencyRegister.DependencyRegisterContainer(); IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B"); bll.ShowResult(); } ////同時運行 IOCMethod2() 和 IOCMethod4()
結果對象
這樣就是實現了子類多個的 IOC 容器註冊。(注意,key必定要區分大小寫)
【帶參的構造函數】
Web程序與數據庫交互的時候,須要從前臺獲取查詢條件,我在 AnalyseB 中寫了一個帶有 string 類型的構造函數。代碼以下
public class AnalyseB:IBLL.IAnalyse { public string StrWhere { get; set; } /// <summary> /// 查詢條件的構造函數 /// </summary> /// <param name="strWhere"></param> public AnalyseB(string strWhere) { this.StrWhere = strWhere; } ////使用依賴注入 [Dependency] public IDAL.IAnalyse dal { get; set; }
public void ShowResult() { dal.ShowResult2(StrWhere); } }
//// 修改 core 層 容器註冊方法 public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(string)))); return container; } ////UI 層調用代碼以下 private static void IOCMethod4() { IUnityContainer container = DependencyRegister.DependencyRegisterContainer(); IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B", new ParameterOverride("strWhere", " WHERE 1=1 ")); bll.ShowResult(); }
AnalyseB 構造函數帶有string 類型的參數,在 容器註冊的時候,須要註冊 參數的類型 new InjectionConstructor(typeof(string),typeof(param2),...) (這裏也能夠是常量)。調用時用ParameterOverride(構造函數參數名,參數值) 來從新給參數賦值。
若是參數是其它類型又怎麼辦。例如數據以表格形式呈現時,須要分頁。我在BLL 層加了一個分頁接口。修改代碼
////新增分頁接口 public interface IPager { string GetPager(); } public class AnalysePager : IBLL.IPager { public string GetPager() { return "數據已分頁"; } } public class AnalyseB:IBLL.IAnalyse { public string StrWhere { get; set; } public IBLL.IPager Pager { get; set; } public AnalyseB(IBLL.IPager pager, string strWhere) { this.Pager = pager; this.StrWhere = strWhere + pager.GetPager(); } ////使用依賴注入 [Dependency] public IDAL.IAnalyse dal { get; set; } public void ShowResult() { dal.ShowResult2(StrWhere); } } ////修改core層 方法 public class DependencyRegister { public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IPager,BLL.AnalysePager>() .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string)))); return container; } } ////UI 層代碼不變
運行結果:
【屬性注入】
修改一下構造函數,把參數 IPager 提成屬性。 代碼以下
public class AnalyseB:IBLL.IAnalyse { public string StrWhere { get; set; } public IBLL.IPager Pager { get; set; } /// <summary> /// 查詢條件的構造函數 /// </summary> /// <param name="strWhere"></param> public AnalyseB(IBLL.IPager pager, string strWhere) { this.Pager = pager; this.StrWhere = strWhere + pager.GetPager(); }
public AnalyseB(string strWhere) { this.StrWhere = strWhere; } ////使用依賴注入 //[Dependency] public IDAL.IAnalyse dal { get; set; } public void ShowResult() { StrWhere += Pager.GetPager(); dal.ShowResult2(StrWhere); } //// core public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IPager, BLL.AnalysePager>() //.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-C", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string)))); .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-D", new InjectionMember[] { new InjectionConstructor(typeof (string)), new InjectionProperty("Pager"), new InjectionProperty("dal"), }); return container; }
本身在實際使用過程總結了幾點:
1.使用屬性注入,屬性不能再構造函數中使用,不然會報爲實例化對象異常。(關於這點本身持懷疑態度,有多是本身不正確的使用形成的。但願和你們討論)
2.BLL.AnalyseB 自己有個屬性 dal. 若是使用屬性注入,則全部屬性都須加入 InjectionMember[] .
3.最好使用構造注入。
(以上三點是在項目使用過程當中,本身總結出來。非權威,非標準,有不對的地方但願你們指出。`(*∩_∩*)′)
【方法注入】
除開構造注入,屬性注入,還有方法注入。使用與屬性注入差很少。方法注入尚沒有在實際項目中應用過,下面例子是參考其它兩種注入方法寫的
////修改此類,增長字段_pager 和 方法 SetPager public class AnalyseB:IBLL.IAnalyse { public string StrWhere { get; set; } public IBLL.IPager Pager { get; set; } public IBLL.IPager _pager; public void SetPager(IBLL.IPager pager) { this._pager = pager; } /// <summary> /// 查詢條件的構造函數 /// </summary> /// <param name="strWhere"></param> public AnalyseB(IBLL.IPager pager, string strWhere) { this.Pager = pager; this.StrWhere = strWhere + pager.GetPager(); } public AnalyseB(string strWhere) { this.StrWhere = strWhere; } ////使用依賴注入 [Dependency] public IDAL.IAnalyse dal { get; set; } public void ShowResult() { //StrWhere += Pager.GetPager(); StrWhere += this._pager.GetPager(); dal.ShowResult2(StrWhere); } ////增長core層的注入方式 container..RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-E", new InjectionMember[] { new InjectionConstructor(typeof (string)), new InjectionMethod("SetPager",container.Resolve<IBLL.IPager>()), }); ////UI 層調用 /// <summary> /// 方法注入 /// </summary> public static void IOCMethod6() { IUnityContainer container = DependencyRegister.DependencyRegisterContainer(); IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-E", new ParameterOverride("strWhere", " WHERE 1=1 ")); bll.ShowResult(); }
(我的以爲方法注入很雞肋,其實就是屬性注入)
以上是我在項目運用過程當中總結出來的一些心得,尚有許多不足的地方,先拋磚引玉,與你們共同討論,共同窗習。