`
zxlyecf2
  • 浏览: 133531 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

IoC容器Autofac

    博客分类:
  • ioc
 
阅读更多

一、一个没有使用IoC的例子

IoC的全称是Inversion of Control,中文叫控制反转。要理解控制反转,可以看看非控制反转的一个例子。

public class MPGMovieLister
   {
       public Movie[] GetMPG()
       {
           var finder = new ListMovieFinder();
           var allMovies = finder.FindAll();

           return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
       }
   }

 

public class ListMovieFinder
   {
       public List<Movie> FindAll()
       {
           return new List<Movie>
                      {
                          new Movie
                              {
                                  Name = "Die Hard.wmv"
                              },
                          new Movie
                              {
                                  Name = "My Name is John.MPG"
                              }
                      };
       }
   }

 

上面的例子中,类MPGMovieLister的作用是列出所有的mpg类型的电影,其中调用了类ListMovieFinder类的方法FindAll()来获取所有的电影。

这段代码看起来还不错,已经符合当前的需求了。

二、当需求发生变动时,非IoC遭遇到的困境

假如,这个时候,movie的列表获取不是直接创建一个list获取,而要求从某个文本文件读取,或者是数据库获取,又或者从web service中获取,我们怎么办?

第一步,再实现一个类, 比如FileMovieFinder,来实现从文本文件中读取Movie列表,再把MPGMovieLister中的这行代码,

     var finder = new ListMovieFinder(); 
替换成

    var finder = new FileMovieFinder(); 
那么这行代码就又能够符合要求了。

 

新的MPGMovieLister代码是这个样子:

 public class MPGMovieLister
   {
       public Movie[] GetMPG()
      {
            var finder = new FileMovieFinder();
           var allMovies = finder.FindAll();
           return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
       }
   }

 

如果底层--获取数据的方式不确定,或者经常更改,MPGMovieLister的代码岂不是要频繁改动? 

三、使用IoC彻底解决问题:

MPGMovieLister的功能都是依赖着具体的类,ListMovieFinder,FileMovieFinder。当需求发生变化的时候,就会导致MPGMovieLister的代码也要做相应的改动。

也就是说,MPGMovieLister直接依赖于ListMovieFinder和FileMovieFinder了。

跳出来看,MPGMovieLister的功能只是负责从列表中找出MPG的movie, 至于movie从什么地方来的,不是MPGMovieLister的职责,它也不需要关心。

而解耦合的方法就是”依赖于抽象,而不是依赖于具体”.

(这个例子非常类似于我们的做开发时候的持久层(数据层)和业务逻辑层,其实业务逻辑层也不关心数据是如何提供的,所以业务逻辑层也应当与持久层解耦合。)

 

实际解决之后的代码:

public class MPGMovieLister
   {
       public Movie[] GetMPG()
      {
            var finder = MovieFinderFactory.GetFinder();
           var allMovies = finder.FindAll();
           return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
       }
   }
 

public class MovieFinderFactory
{
     public static IMovieFinder GetFinder()
     {
         return new FileMovieFinder();
     }
} 

public interface IMovieFinder
{
    List<Movie> FindAll()
}

 

 这里MPGMovieLister就依赖于IMovieFinder接口(依赖抽象), 实际运行时候的实例化由MovieFinderFactory来提供。这样,不同的Movie数据源只需要一个实现IMovieFinder 的类就可以了,不会对MPGMovieLister产生任何影响。

 到这里,实际上已经完成了IoC, 控制权最初取决于MPGMovieLister中是如何实例化MovieFinder 的,现在它已经交出控制权,交由外部来提供具体实例对象了。

这里的MovieFinderFactory就已经是一个简陋的IoC容器功能了。

 

四、总结

IoC这种解决依赖的方法是面向对象方法的使用。现实世界中,这种方法无处不在。

比如,汽车不会强依赖于某个品牌的轮胎,任何公司生产的轮胎,只要符合汽车的接口,就可以装在这个汽车上使用。

还有电脑的USB接口,只要符合USB标准的外设,就都能够接上电脑使用。

 

解除依赖不仅让代码结构看起来更加合理,其带来的另一个好处是,各个部分可以单独的做单元测试,使得单元测试能够更加容易的进行。这个对于一些复杂度高的项目,对于保证项目的稳定性和可用性非常有意义。

真正的IoC容器比上面的MovieFinderFactory自然要好用和适用的多。下一篇文章将会介绍一个非常棒的IoC框架Autofac.

 

IoC容器Autofac(2)

一、使用自定义工厂类实现IoC的例子

 

我们回顾一下之前的代码:

//这个类的作用是筛选出MPG类型的电影
public class MPGMovieLister:IMovieFinder
{
  public Movie[] GetMPG()
  {
       var finder = MovieFinderFactory.GetFinder();//这里调用工厂类获取具体的实例,得到一个电影列表
       var allMovies = finder.FindAll();
       return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
   }
}
 

public class MovieFinderFactory
{
     public static IMovieFinder GetFinder()
     {
         return new ListMovieFinder();
     }
} 

public class ListMovieFinder :IMovieFinder
{
   public List<Movie> FindAll()
   {
       return new List<Movie>
                  {
                      new Movie
                          {
                              Name = "Die Hard.wmv"
                          },
                      new Movie
                      {
                          Name = "My Name is John.MPG"
                      }
                 };
   }
}

public interface IMovieFinder { List<Movie> FindAll() }

 

这里MPGMovieLister已经不和具体的MovieFinder耦合了,而是依赖于MovieFinderFactory工厂类提供的IMovieFinder接口的具体实现来取Movie数据。

所以工厂类只要返回不同的实现IMovieFinder的实例,就能够让MovieLister从列表,文本,数据库,web service …… 中获取数据。

二、改造代码,去除MovieFinderFactory

在应用Autofac替换MovieFinderFactory之前,我们先从代码中去掉MovieFinderFactory, 改动之后的代码是这样:

public class MPGMovieLister
{
    private readonly IMovieFinder _movieFinder;
    //增加了构造函数,参数是IMovieFinder对象
    public MPGMovieLister(IMovieFinder movieFinder)
    {
         _movieFinder = movieFinder;
    }

    public Movie[] GetMPG()
    {
     var allMovies = _movieFinder.FindAll();
     return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
    }
}

public interface IMovieFinder
{
    List<Movie> FindAll()
} 

 

我们去掉了工厂类MovieFinderFactory, 改造了MPGMovieLister, 添加了一个构造函数, 构造函数要求使用MPGMovieLister时,需要提供一个IMovieFinder的实例。

三、应用Autofac替代工厂类

应用Autofac改造上面的代码。

第一步: 从Nuget中添加Autofac引用

第二步:

* 创建一个ContainerBuilder对象(ContainerBuilder从字面的意思就是用来创建Container(容器)的,而Conainter就是我们从中取各种我们需要对象的地方)

* 注册我们后面将从容器中取出对象的类型。

代码是这样:

var builder = new ContainerBuilder();//

builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();//注册ListMovieFinder类型,这里的AsImplementedInterfaces表示以接口的形式注册
builder.RegisterType<MPGMovieLister>();//注册MPGMovieLister类型

 

* 创建容器

 

_container = builder.Build();

 

 

 

第三步: 在程序中使用 _container容器:

 

 

var lister = _container.Resolve<MPGMovieLister>();

foreach (var movie in lister.GetMPG())
{
     Console.WriteLine(movie.Name);
} 

 

 

 

 

理解一下Autofac为我们在背后做了什么:

首先,我们注册了类型ListMovieFinder和MPGMovieLister,这样容器就能够知道如何创建这两种类型的实例了。(类其实是创建对象的模板,当我们把模板注册给Autofac, 它就会遵循这个模板为我们提供实例)

后面的代码中,我们调用Resolve方法,取出一个MPGMovieLister的实例。

_container.Resolve<MPGMovieLister>();

 

这里还有一个需要解释的,对于MPGMovieLister类型,我们为Autofac提供了类型, 但是当Autofac创建MPGMovieLister的实例, 调用它的构造函数的时候,却遇到了问题:

它的构造函数需要提供一个IMovieFinder的实例作为参数的, 聪明的Autofac要在自己的容器里找找,看看没有有办法提供一个IMovieFinder的实例。

这个时候Autofac会发现我们注册过ListMovieFinder, 并且通过AsImplementedInterfaces()方法,指明了就是为接口IMovieFinder提供实例的。

所以Autofac会创建一个ListMovieFinder的实例,作为创建MPGMovieLister时,提供给构造函数的参数。

builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();

 

四、当需求发生变动, Autofac如何应对?

上面的例子中,我们的类ListMovieFinder实现了IMovieFinder接口, 实际运行中,是由它来提供数据。

假如这个时候,我们要从数据库中获取数据,怎么办?

非常简单,创建一个类DBMovieFinder继承IMovieFinder接口, 然后注册给Autofac就可以了。 这样程序就非常容易的切换到从数据库中取数据了。

注册相关改动的代码是这样的:

var builder = new ContainerBuilder();
builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();

//这里注册了DBMovieFinder, 这个类继承IMovieFinder接口。因为它也使用了AsImplementedInterfaces,它会覆盖ListMovieFinder的注册。
builder.RegisterType<DBMovieFinder>().AsImplementedInterfaces(); builder.RegisterType<MPGMovieLister>(); 
_container = builder.Build();

 

五、Autofac对程序架构的影响

常见的程序架构大概是: UI层, 业务逻辑层, 持久层(数据层)。

我们可以使用Autofac作为不同层之间的中间人,让UI层依赖于业务逻辑层的抽象接口,业务逻辑层依赖于持久层的接口,而实际运行过程中的实例都由Auotfac来提供。

这样我们就能够解除不同层之间的依赖,将所有的注册类型的操作在一个核心函数或者核心类中实现,那么只要修改这个函数或者类,就能够非常方便的让它们之间的依赖关系发生变化。

 

比如, 在一个大的项目中,持久层和业务逻辑层是并行开发的,而且是不同团队开发,这个时候业务逻辑开发团队的人在没有持久层代码的情况下,如何开始呢?

我们只要定义好持久层的接口, 业务逻辑团队再写一些Stub类(桩类)来实现这些接口,让这些Stub类来替换真正的持久层,所要做的就只是简单的把这些Stub类型注册到Autofac中就可以了。同时做业务逻辑层的单元测试也非常容易了。

分享到:
评论

相关推荐

    IOC容器Auto fac的DEMO

    **IOC容器AutoFac详解** IOC(Inversion of Control),即控制反转,是一种设计模式,它将对象的创建和管理权交给了外部框架或容器,而不是由对象自身来负责。这样可以降低系统的耦合度,提高代码的可测试性和可...

    [IoC容器] Autofac 3.0.2

    Autofac is an IoC container for Microsoft .NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating ...

    Repository模式与IOC的Autofac的完美融合数据操作展示实例

    Autofac是Inversion of Control (IoC)或Dependency Injection (DI)容器的一种,它帮助我们管理对象的生命周期和依赖关系。在本示例中,AutoFac用于实现依赖注入,使得在MvcTest和Services等模块中,可以轻松地获取到...

    Moq的自动模拟IoC容器_C#_下载.zip

    IoC容器,如 Autofac、Unity 和 Ninject,是DI模式的一种实现,它负责管理和配置应用程序中的对象实例。通过将依赖关系的创建和管理从代码中分离出来,IoC容器可以使代码更加灵活、可测试和可维护。开发者只需要告诉...

    Typefac:基于Autofac的TypeScript IoC容器

    Typefac作为IoC容器,负责实例化对象,处理对象的生命周期,并根据需要提供依赖对象。 4. **Autofac移植**: Autofac是.NET平台上一个流行的DI框架,Typefac从Autofac借鉴了许多设计理念和功能。移植到TypeScript...

    C#实现的IOC和AOP框架,供学习

    在C#中,通常通过接口和抽象类来实现依赖注入,同时可以利用微软的Unity、Autofac或Ninject等第三方IOC容器来简化这一过程。IOC容器负责解析依赖关系,根据配置自动创建对象并注入到其他对象中,使得代码更加灵活。 ...

    xunit.ioc:XUnit 的扩展,允许您从依赖注入容器中解析测试类

    Xunit.Ioc 是 XUnit 的扩展,它允许您从依赖注入容器解析测试类。 Autofac 和 Ninject 是开箱即用的,但很容易将它与您的依赖注入容器集成(我们接受拉取请求!)。 为什么这很有用? 能够从容器中解析测试类使...

    有关IOC组件(.net core内置组件,和第三方Autofac组件)的使用,以及自己实现IOC

    **Autofac IOC容器** Autofac是一个流行的第三方DI库,它提供更丰富的功能,比如支持更多的生命周期管理和类型注册方式。Autofac可以很容易地与ASP.NET Core集成,通过`UseAutofac`扩展方法替换默认的服务容器。...

    entity framework+autofac+ioc

    Autofac是一个流行的轻量级依赖注入(DI)容器,也是入侵检测(IOC)容器。它支持.NET框架,包括ASP.NET应用程序。Autofac提供了强大的功能,如生命周期管理、模块化、以及对WCF、ASP.NET MVC和Web API等框架的集成...

    Autofac4 官方文档

    Autofac文档提供了详细的信息和示例,帮助开发者理解IoC容器的使用方法。如果想要深入了解更多的高级用法,文档还包含了如何与WCF、***等其他应用类型集成的指南。Autofac的设计非常灵活,支持多种注册组件的方式,...

    .netcore6 的Autofac使用实例 接口多个实例 ResolveByKey作用域

    这通常包括调用 `services.AddAutofac()` 并使用 `ConfigureContainer` 方法来添加自定义的 Autofac 容器配置。例如: ```csharp public void ConfigureServices(IServiceCollection services) { // 其他服务注册....

    FactoryIoc

    IoC容器如 Autofac、Unity、Ninject 等,可以自动管理对象的生命周期和依赖关系,使得代码更加灵活和易于测试。 **清洁工厂设计模式** 在博客中提到的“清洁工厂”,指的是使用IoC容器改进的传统工厂模式。通过引入...

    Autofac Ioc C# Demo 控制反转

    **Autofac Ioc C# Demo - 控制反转详解** 控制反转(Inversion of Control,IoC)是一种软件设计模式,它将对象的创建和管理权交给容器来处理,而不是由对象自身负责。这种模式使得应用程序的组件之间解耦,提高了...

    autofac+mvc5+三层-ioc

    标题中的"autofac+mvc5+三层-ioc"指的是使用Autofac作为依赖注入容器,在ASP.NET MVC5框架下实现三层架构(通常包括表现层、业务逻辑层和数据访问层)的应用程序,并通过IOC(Inversion of Control,控制反转)来...

    An_IoC_Container_in_15_min

    4. **容器的类型:** 常见的IoC容器有Spring框架(Java)、Autofac(.NET)、Guice(Java)等。它们提供了丰富的功能,如接口绑定、构造函数注入、属性注入等。 5. **构建IoC容器的步骤:** - 定义接口或抽象类:...

    IOC练习事列

    在这个练习中,`MyselfIoc`可能就是我们自定义的IOC容器实现,它将负责实例化对象和管理这些对象的依赖。 **C#中的IOC实现**: C#中实现IOC通常有两种方式:一是使用第三方IOC框架,如Autofac、Unity、Ninject等;...

    Ioc(控制反转)的例子

    在C#中,有许多第三方库提供了IoC容器,如Autofac、Unity、Ninject等。这些库可以帮助我们管理对象的生命周期,以及根据配置自动注入依赖。例如,使用Autofac,我们可以这样注册和解析依赖: ```csharp var ...

    MVC Autofac.dll

    Autofac作为IoC容器,负责创建对象实例,管理它们的生命周期,并负责在需要时注入依赖。 **Autofac的集成**,特别是与ASP.NET MVC的集成,意味着开发者可以在控制器、视图、过滤器和其他MVC组件中方便地使用依赖...

    Autofac:令人上瘾的.NET IoC容器

    Autofac是Microsoft .NET的。 它管理类之间的依赖关系,以使应用程序随大小和复杂性的增长而保持易于更改的状态。 这是通过将常规.NET类视为。取得包裹您可以通过来获取Autofac。 如果您喜欢冒险,。 。得到帮助在...

Global site tag (gtag.js) - Google Analytics