四、Infra層解析
ProDinner使用了Castle.Windsor開源項目,最直接最根本的使用了依賴倒轉,說得通俗點,我們在使用接口的時候,往往可以實現,實現層的多樣化,基於實現接口的多樣化,我們有不同的調用方式,但是在調用接口的時候,我們最終需要選擇那樣實現來運行代碼,例如:
public interface IA { void Print(); } public class AA : IA { public void Print() { Console.Write("AA實現"); } } public class BB : IA { public void Print() { Console.Write("BB實現" + "_BB"); } }
無論哪種實現,我們在使用IA接口的時候,最終需要給接口實例化一個對象,要么是AA,要么是BB。這就是C#基本的多態。在面對復雜的項目層次划分的時候,如果我們有多種實現,或者這種實現會不停的變更時候,其實我們依然擺脫不了修改代碼的噩運。Castle.Windsor實現了依賴倒轉,通過配置來告訴程序當前是誰來實現接口,所以我們在Core、Data層沒有看見任何具體的實例邏輯代碼。順便帶一句Caslte是個開源項目,據我所知ASP.NET MVC很大程度上借鑒了該開源項目。另外博客園李會軍前輩的博客有介紹這方面的文章。
官網:http://www.castleproject.org
究竟如何是實現這種高抽象化的接口配置呢,看看實例吧
首先定義2個接口
public interface IA { void Print(); } public interface IB { void Set(string str); }
然后分別實現這2個接口
public class AA : IA { public void Print() { Console.Write("AA實現"); } } public class BB : IB { public void Set(string str) { Console.Write(str + "_BB的實現"); } }
調用實現代碼:
static void Main(string[] args) { IWindsorContainer wcs = new WindsorContainer(new Castle.Windsor.Configuration.Interpreters.XmlInterpreter("http://www.cnblogs.com/XMLFile.xml")); wcs.AddComponent("mykey", typeof(IA), typeof(AA)); wcs.AddComponent("format", typeof(IB), typeof(BB)); IA log = (IA)wcs["mykey"]; log.Print(); }
運行結果:
再玩得復雜點,修改AA類實現代碼如下:
public class AA : IA { IB _ib; public AA(IB ib) { _ib = ib; } public void Print() { Print(_ib); } public void Print(IB ib) { Console.Write("AA實現"); ib.Set("調用接口"); } }
運行結果:
最后附有實例的源代碼,可以運行一下試試看,我想看懂了這個實例的同學應該發現他的神奇之處了,我沒有New任何一個對象,實現了,對AA和BB具體實現的調用,也就是說代碼居然是接口調接口,實現了具體操作。
回到我們這里需要講解的ProDinner,Infra層其實就是運用了Castle的這種特定的方式實現了依賴倒轉。
public static class IoC { private static readonly object LockObj = new object(); private static IWindsorContainer container = new WindsorContainer(); public static IWindsorContainer Container { get { return container; } set { lock (LockObj) { container = value; } } } public static T Resolve<T>() { return container.Resolve<T>(); } public static object Resolve(Type type) { return container.Resolve(type); } }
全篇代碼並不復雜,但為后續的依賴倒轉提供了幾個基礎的接口實現,其實吧這要說C#有T這么個好東西哇。
private static IWindsorContainer container = new WindsorContainer();聲明一個唯一的依賴倒轉容器
Container屬性通過加鎖的方式保證這個容器的唯一性,就如同我們Entity Framework框架中DbContext一樣保證唯一
Resolve就是為實現不同的類型容器而實現的接口。
這層為實現抽象層和后續的業務實現層建立了橋梁,Castle是個很好的開源項目,有時間可以看看源代碼,這節內容比較多,我附上我的源代碼,可以再繼續討論。
本節源代碼:http://files.cnblogs.com/aspnetdream/ConsoleApplication2.rar