码迷,mamicode.com
首页 > 其他好文 > 详细

1、初识Autofac

时间:2015-01-20 17:33:29      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:

      近一两年写了很多小Web系统,逐渐开始变得熟练。现在最困扰我的,并不是某种具体需求如何去实现,而是如何更为优雅的规划整个应用程序。尽量降低不同的层之间的耦合,提高维护性和扩展性。而这种低耦合,基于接口的开发模式也恰好是应用很多先进开发手段的基础,诸如单元测试,TDD等。扯远了,还是从一个吃饭的例子说起。请原谅我是一个吃货...
      新建一个控制台应用程序:

namespace DEMO
{
    /// <summary>
    /// 吃饭1.0版
    /// </summary>
   public class Dinner
    {
       public void HotPot()
       {
           Console.WriteLine("重庆火锅...");
       }
    }

  public  class Person
    {
      private Dinner m_Dinner;

      public Person()
      {
          m_Dinner = new Dinner();
      }

      public void Dinner()
      {
          m_Dinner.HotPot();
      }
    }
}

       (此处省略了客户端代码),有一个人类,持有一个吃饭类的引用,在人类构造函数中初始化吃饭类并调用吃饭类的方法。此时“人"和”吃饭"发生了硬耦合,如果我某天想吃烧烤,只能在吃饭类中新增一个烧烤方法并修改人类。老鸟会告诉你,你可以通过接口来降低耦合度。so,我们来改一改代码。

namespace DEMO
{
    /// <summary>
    /// 吃饭2.0版
    /// </summary>

    public interface IDinner
    {
        void Eating();
    }

    public class HotPot:IDinner
    {
        public void Eating()
        {
            Console.WriteLine("重庆火锅...");
        }
    }

  public  class Person
    {
      private IDinner m_IDinner;

      public Person()
      {
          m_IDinner = new HotPot();
      }

      public void Dinner()
      {
          m_IDinner.Eating();
      }
    }
}

      创建一个吃饭接口,调用吃饭接口的方法,如果要更改实现,就更改接口的初始化语句,并添加相应的实现即可。看起来好像高端了那么一点点,利用了接口的多态。人类的构造函数里的这句 m_IDinner = new HotPot(); 一直是让我想不明白的地方。接口总要实例化到某个具体的对象上,如人类事先已经知道HotPot火锅类实现了吃饭接口,那这种初始化纯属脱裤子放屁多此一举,我直接使用火锅类不就得了吗?还费劲巴拉的弄个接口干什么呢? 换句话说,这种指定应该在人类的外部去做,人类本身并不应该去承担这种职责,人类就知道吃饭,至于吃什么,那是另外一个职责,应该分离出来。
      这种困惑并不是我独有的,为此有很多高手想了很多办法来解决,就是目前所说的IOC框架,IOC是控制反转的简写,就是把这种初始化或者new的职责,从类的内部转移到类的外部,一般是在 app_start的地方进行统一的初始化。解除了类的耦合,从而真正实现面向接口编程。.NET平台上目前也涌现了一大批IOC框架,目前最主流的就是Autofac。闲话少说,直接改代码:
      首先引入Autofac,你可以手动引入DLL或者直接用NUGET安装,VS下当然推荐NUGET了,写一句控制命令就搞定了:PM> install-package autofac ,这次贴出全部代码:  

namespace DEMO
{
    /// <summary>
    /// 吃饭3.0版
    /// </summary>

    public interface IDinner
    {
        void Eating();
    }

    public class HotPot : IDinner
    {
        public void Eating()
        {
            Console.WriteLine("重庆火锅...");
        }
    }

    public class Person
    {
        readonly IDinner m_IDinner;
        
        public Person(IDinner idinner)
        {
            m_IDinner = idinner;
        }

        public void Dinner()
        {
            m_IDinner.Eating();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<Person>();
            builder.RegisterType<HotPot>().As<IDinner>();
            using (var container = builder.Build())
            {
                var person = container.Resolve<Person>();
                person.Dinner();
            }
            Console.Read();
        }
    }
}

        Person的构造带一个IDinner参数,也就是说在初始化的时候必须赋它一个IDinner实例。这个构造函数是写给autofac使用的,autofac会自动初始化IDinner的一个实例并传给Person的构造函数。这样一来,Person类中没有了类似 m_IDinner = new HotPot();这样的代码。Person类依赖接口IDinner,而接口是构造函数中由外部注入的,这就是“构造依赖注入”,如此一来,Person类和火锅类彻底没有了关系。从而实现了彻底解耦合。
       var builder = new ContainerBuilder(); //创建一个容器建造器
       builder.RegisterType<Person>();//将这个类型注册到autofac,
       builder.RegisterType<HotPot>().As<IDinner>();//将HotPot类作为IDinner的实例注册
       var person = container.Resolve<Person>();//Resolve可以理解为从容器中实例化一个对象出来,在调用Person的构造函数时,antofac会自动实例化一个HotPot对象并作为参数。

       上述的东西都是一些API的用法,看看就明白。
       如果我要更换实现,比如吃烧烤,就写一个烧烤实现,再更改一下注册类型即可,Person类完全不用动。在main函数中写了一大堆代码才实现了解耦,也许有人会觉得得不偿失,在网站开发的过程中,DAL,BLL,UI只有实现解耦合,才能实现真正的分层协作开发。以上述代码为例,IDinner接口的实现由另一个人来写,可能他还没写好,你此时可以自己写一个”桩“类实现IDinner接口,然后写代码即可,不必操心他的开发进度或者Bug会干扰到你。只需要注册一次即可,是不是很犀利?
       此外autofac还对asp.net mvc提供了良好的集成,有专门的类库用于mvc开发。
       以上是我刚刚接触autofac的一些浅见。    

1、初识Autofac

标签:

原文地址:http://www.cnblogs.com/echoshinian100/p/4236270.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!