ASP.NET MVC经典项目ProDinner项目解析(4)

四、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
 
 
posted @ 2013-04-30 23:08  aspnetdream  阅读(2239)  评论(5编辑  收藏  举报