注意:本文为原创文章,任何形式的转载、引用(包括但不限于以上形式)等,须先征得作者同意,否则一切后果自负。

简介

Autofac 是一个令人着迷的.NET IoC 容器。

它管理类之间的依赖关系。当应用程序的规模和复杂性随着时间不断增长时,也能易于更改。这是通过将常规 .NET 类视为组件来实现的。

入门

将 Autofac 集成到我们的应用程序的基本模式是:

  • 时刻牢记用控制反转(IOC)来构建我们的应用程序。
  • 添加Autofac引用。
  • 在应用程序启动时…
  • 创建一个ContainerBuilder。
  • 注册组件。
  • 构建容器并将其存储以备后用。
  • 在应用程序执行期间…
  • 从容器创建一个生命周期范围。
  • 使用生命周期范围来解析(resolve)组件的实例。

构建应用程序

控制反转背后的思想是:与其将应用程序中的类捆绑在一起,让类“新建”它们的依赖关系,不如在类构造期间把依赖项传递进来,如果每次传递的依赖项不相同,则可以随时切换依赖关系并调用相应的依赖项的实现。

对于我们的示例应用程序,我们将定义一个将当前时间写出的类。但是,我们不希望将它绑定到Console,因为我们希望能够稍后测试该类,或者在控制台不可用的地方使用它。

我们将尽可能地把写出时间的机制抽象化,因为如果我们以后想把它变成一个写出明天日期的程序版本,那么就可以快速实现该功能。

代码如下:

public interface IOutput
{
void Write(string content);
}
public class Output : IOutput
{
public void Write(string content)
{
Console.WriteLine(content);
}
}
public interface ITodayWriter
{
void WriteDate();
}
public class TodayWriter : ITodayWriter
{
private IOutput _output; public TodayWriter(IOutput output)
{
_output = output;
} public void WriteDate()
{
_output.Write(DateTime.Now.ToString());
}
}

现在我们有了一个合理的结构化的依赖集,下面我们就把Autofac加入进来!

添加 Autofac 引用

第一步是将Autofac引用添加到我们的项目中。

对于我们的示例,仅使用核心Autofac包就够了,因为该包包含了我们所要使用的全部核心功能。

引入Autofac最简单的方法是通过NuGet。

应用启动

在应用程序启动时,我们需要创建一个ContainerBuilder并在其中注册我们的组件。

组件可以是一个表达式、.NET类型或其他代码(该代码公开一个或多个服务,并可以接受其他依赖项)。

简单来说,考虑一个实现接口的 .NET 类型,像这样:

public class SomeType : IService
{
}

我们可以用以下两种方法来解决这个问题:

  • 作为类型本身,SomeType
  • 作为接口,IService

在这种情况下,组件是SomeType,它公开的服务是SomeType和IService(这一点你可能不太明白,不过没关系,后面我们将会讲解)。

在Autofac中,您可以使用以下内容进行注册ContainerBuilder:

// 创建一个构造器
var builder = new ContainerBuilder(); // 注册组件,并公开它的服务
builder.RegisterType<SomeType>().As<IService>(); // 如果你想把组件自身也注册成服务,那么可以使用AsSelf()
builder.RegisterType<SomeType>().AsSelf().As<IService>();

对于我们的示例程序,我们需要注册我们所有的组件(类)并公开它们的服务(接口),以便可以很好地连接起来。

我们还需要存储容器,方便以后用它来解析类型。

using System;
using Autofac; namespace DemoApp
{
public class Program
{
private static IContainer _Container { get; set; } static void Main(string[] args)
{
var builder = new ContainerBuilder(); builder.RegisterType<Output>().As<IOutput>();
builder.RegisterType<TodayWriter>().As<ITodayWriter>(); Container = builder.Build(); //该方法我们后面实现它
WriteDate();
}
}
}

现在我们有了一个容器其中所有组件都已注册,并且它们公开了适当的服务。让我们来使用它吧。

应用程序执行

在应用程序执行期间,我们需要使用我们注册的组件。我们可以通过生命周期范围解析它们来做到这一点。

容器本身就是一个生命周期范围,从技术上讲,我们可以直接从容器中解决问题。但是,我非常不建议直接从容器解析

当我们解析一个组件时,根据我们定义的实例范围,会创建该对象的一个​​新实例。(解析一个组件大致相当于调用“new”来实例化一个类。这真的真的过于简单化了,但从类比的角度来看,这个比较很恰当。)一些组件可能需要被释放(就像它们实现了IDisposable一样)——Autofac可以在生命周期范围被释放时自动为我们处理那些组件的释放。

但是,容器在应用程序的整个生命周期内都存在。如果我们直接从容器中解决很多东西,等到最终,我们可能会有很多东西等待释放。这非常的不好(如果我们这样做,可能会发生“内存泄漏”的事故)。

相反,如果我们从容器创建一个子生命周期范围并从中解析。当我们完成组件解析后,Autofac会帮我们自动释放子作用域并为清理所有内容。

如果我们使用Autofac 集成库时,这个子作用域的创建主要是自动为我们完成的,因此我们不必考虑它。

对于我们的示例应用程序,现在我们将实现“WriteDate”方法,它从一个子生命周期范围获取写出结果,并在完成时自动处理该生命周期。

namespace DemoApp
{
public class Program
{
private static IContainer Container { get; set; } static void Main(string[] args)
{
// 该内容在上面已经实现,不再重复
} public static void WriteDate()
{
// 创建一个子生命周期范围,解析ITodayWriter服务,调用方法,调用结束后被子生命周期范围释放掉
using (var scope = Container.BeginLifetimeScope())
{
var writer = scope.Resolve<ITodayWriter>();
writer.WriteDate();
}
}
}
}

现在当我们运行程序时......

  • 该WriteDate方法创建了一个生命周期范围,从中可以解析依赖项。这样做是为了避免任何内存泄漏 - 如果ITodayWriter或其依赖项是一次性的,它们将在范围被释放时自动释放。
  • 该WriteDate方法从生命周期范围内手动解析ITodayWriter。(这里是“服务地点”。)在内部……
    • Autofac 看到ITodayWriter映射到TodayWriter,所以开始创建一个TodayWriter.
    • Autofac 认为在其构造函数中TodayWriter需要一个IOutput。(这是“构造函数注入”。)
    • Autofac 看到IOutput映射到Output,所以创建一个新Output实例。
    • Autofac 使用新Output实例来完成构建TodayWriter.
    • Autofac 返回完全构造的TodayWriter供WriteDate消费。
  • 对writer.WriteDate()的调用会转到全新的TodayWriter.WriteDate(),因为这是已解决的问题。
  • Autofac生命周期范围已释放。从该生命周期范围解析的任何一次性项也将被处理。

之后,如果我们想让我们的应用程序编写一个不同的日期,我们可以实现一个不同的ITodayWriter,然后在应用程序启动时更改注册。我们不需要更改任何其他类。这是不是非常的棒,这就是控制反转!

 

Autofac入门的更多相关文章

  1. Autofac 入门

    Autofac 入门文档 原文链接:http://docs.autofac.org/en/latest/getting-started/index.html 在程序中使用Autofac的基本模式是: ...

  2. 一、Autofac入门

    想要将autofac集成到你的应用程序中需要经过如下步骤: 1.使用控制翻转(IoC)的思想架构你的应用程序: 2.添加autofac引用: 3.在应用程序入口...(At application s ...

  3. [翻译] Autofac 入门文档

    原文链接:http://docs.autofac.org/en/latest/getting-started/index.html 在程序中使用Autofac的基本模式是: 用控制反转(IoC)的思想 ...

  4. .NET手记-Autofac入门Getting Started

    内容主要翻译自官方文档,原文请看:http://autofac.readthedocs.org/en/latest/getting-started/index.html#application-sta ...

  5. [转]ASP.NET MVC IOC 之AutoFac攻略

    本文转自:http://www.cnblogs.com/WeiGe/p/3871451.html 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用A ...

  6. ASP.NET MVC IOC 之AutoFac攻略

    一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天,发现这个东东确实是个高大上的IOC容器~ Autofa ...

  7. 不复杂的Autofac注入

    private static void SetAutofacWebAPI() { var builder = new ContainerBuilder(); #region 配置注册方法 string ...

  8. Autofac 一个使用Demo

    一:接口 二:实现: 三:调用: 首先上图: 一:接口代码 public interface IPersonDa { PersonEntity Get(int id); } 二:实现 public c ...

  9. ASP.NET MVC IOC 之AutoFac

    ASP.NET MVC IOC 之AutoFac攻略 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天, ...

  10. 【AutoFac】依赖注入和控制反转的使用

    在开始之前首先解释一下我认为的依赖注入和控制反转的意思.(新手理解,哪里说得不正确还请指正和见谅) 控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的 ...

随机推荐

  1. Razor 视图引擎 &ndash; ASP.NET MVC 4 系列

           Razor 视图引擎是 ASP.NET MVC 3 开始扩展的内容,并且也是默认视图引擎.        Razor 通过理解标记的结构来实现代码和标记之间尽可能顺畅的转换.下面的例子演 ...

  2. Git学习(一)——Git介绍与安装

    一.Git诞生 Linus在1991年创建了Linux,从此,Linux系统不断发展,成为最大的服务器系统软件. 2005年,Linus用C编写了一个分布式版本控制工具--Git. 二.集中式vs分布 ...

  3. uiatuomator如何调试

    博主较笨,在使用junit 和uiatuomator结合时不知道怎么调试,因为uiatuomator一直是push在手机上,而junit是需要代码运行的,那我该怎么办,现在发一下不知道是哪位大神写的代 ...

  4. 七周七语言——Prolog(二)

    1  递归 首先来看一个知识库: father(zeb,john_boy_sr). father(john_boy_sr,john_boy_jr). ancestor(X,Y):-father(X,Y ...

  5. 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览

    ### 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览 http://segmentfault.com/a/1190000002583569

  6. Linux常用C函数---内存控制篇

    函数讲解部分参考http://net.pku.edu.cn/~yhf/linux_c/ calloc(配置内存空间) 相关函数 malloc,free,realloc,brk 表头文件 #includ ...

  7. POJ训练计划1459_Power Network(网络流最大流/Dinic)

    解题报告 这题建模实在是好建.,,好贱.., 给前向星给跪了,纯dinic的前向星居然TLE,sad.,,回头看看优化,.. 矩阵跑过了.2A,sad,,, /******************** ...

  8. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

  9. 解决eclipse报PermGen space异常的问题

    开发中遇到Eclipse报错:java.lang.OutOfMemoryError: PermGen space. 网搜到三种解决方法,最终还是第三种方法起了作用.记录日志,备用. 原文地址: htt ...

  10. 移动端分享到微信和QQ

    关于在H5页面实现分享到微信和QQ,当初做的时候由于没有做过这方面的功能,也查了很多资料,找了很多插件,试了很多方法,大部分的都是点击后出现一个二维码,这不 符合我的需求,所以在网上找了一个 nati ...