四、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是个很好的开源项目,有时间可以看看源代码,这节内容比较多,我附上我的源代码,可以再继续讨论。
本节源代码:https://files.cnblogs.com/aspnetdream/ConsoleApplication2.rar