猿教程 Logo

Autofac教程:入门实例

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

  • 用控制反转 (ioc) 来构造你的应用程序。

  • 添加Autofac引用。

  • 在应用程序启动时...

  • 创建一个ContainerBuilder。

  • 注册组件。

  • 构建容器并存储以供以后使用。

  • 在应用程序执行期间...

  • 从容器创建一个生命周期范围。

  • 使用生命周期范围来解决组件的实例。

  • 本入门指南将引导您完成简单控制台应用程序的这些步骤。 一旦您将基础知识关闭,您可以查看维基的其余部分,了解更高级的WCF,ASP.NET和其他应用程序类型的使用和集成信息。



构建应用程序

控制反转的想法是,让类“新建”它们的依赖关系,并不是将应用程序中的类绑定在一起,是将其切换到所有依赖关系,而不是在类构造期间传递。 如果你想要更多控制反转的资料的话,Martin Fowler有一篇很好的文章来解释依赖注入/反转控制。

对于我们的示例应用程序,我们将定义一个将当前日期写入的类。 但是,我们不希望它与控制台相关联,因为我们希望能够稍后测试该类,或者在控制台不可用的地方使用它。

我们还将尽可能地让写入日期的机制被抽象出来,所以如果我们希望在稍后的版本中交换一个写明日期的版本,那将会很快。

我们会这样做:

using System;
namespace DemoApp
{
  // This interface helps decouple the concept of
  // "writing output" from the Console class. We
  // don't really "care" how the Write operation
  // happens, just that we can write.
  public interface IOutput
  {
    void Write(string content);
  }
  // This implementation of the IOutput interface
  // is actually how we write to the Console. Technically
  // we could also implement IOutput to write to Debug
  // or Trace... or anywhere else.
  public class ConsoleOutput : IOutput
  {
    public void Write(string content)
    {
      Console.WriteLine(content);
    }
  }
  // This interface decouples the notion of writing
  // a date from the actual mechanism that performs
  // the writing. Like with IOutput, the process
  // is abstracted behind an interface.
  public interface IDateWriter
  {
    void WriteDate();
  }
  // This TodayWriter is where it all comes together.
  // Notice it takes a constructor parameter of type
  // IOutput - that lets the writer write to anywhere
  // based on the implementation. Further, it implements
  // WriteDate such that today's date is written out;
  // you could have one that writes in a different format
  // or a different date.
  public class TodayWriter : IDateWriter
  {
    private IOutput _output;
    public TodayWriter(IOutput output)
    {
      this._output = output;
    }
    public void WriteDate()
    {
      this._output.Write(DateTime.Today.ToShortDateString());
    }
  }
}

现在我们有一个合理的结构(如果设计的)一组依赖,让我们获取Autofac!


添加Autofac依赖

第一步是将Autofac引用添加到项目中。 对于这个例子,我们只使用核心Autofac。 其他应用程序类型可能会使用其他Autofac集成库。

最简单的方法是通过NuGet。 “Autofac”软件包具有您需要的所有核心功能。



Application Startup

在应用程序启动时,您需要创建一个ContainerBuilder并使用它来注册您的组件。 组件是表达式,.NET类型或其他一些暴露一个或多个服务并可以承担其他依赖关系的代码。

简单来说,参考一个实现接口的.NET类型,如下所示:

public class SomeType : IService
{
}

您可以通过以下两种方式之一来处理该类型:

  • 作为类型本身,SomeType

  • 作为接口,一个IService

在这种情况下,组件是SomeType,它暴露的服务是SomeType和IService。

在Autofac中,您可以使用ContainerBuilder注册这样的东西:

// Create your builder.
var builder = new ContainerBuilder();

// Usually you're only interested in exposing the type
// via its interface:
builder.RegisterType<SomeType>().As<IService>();

// However, if you want BOTH services (not as common)
// you can say so:
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<ConsoleOutput>().As<IOutput>();
      builder.RegisterType<TodayWriter>().As<IDateWriter>();
      Container = builder.Build();
      // The WriteDate method is where we'll make use
      // of our dependency injection. We'll define that
      // in a bit.
      WriteDate();
    }
  }
}

现在我们有一个容器,其中注册了所有组件,并且他们正在暴露适当的服务。 我们来利用它。


运行应用程序

在应用程序执行过程中, 您需要使用注册的组件。通过从生存期范围解决这些操作, 您可以做到这一点。

容器本身是一个生存期范围, 并且您可以从技术上只从容器中正确地解决问题。但是, 建议不要直接从容器解析。

在解析组件时, 根据定义的实例范围, 将创建对象的新实例。(解析组件大致相当于调用 "new" 来实例化类。这真的, 真的简单化, 但从类比的角度来看, 这是很好的。某些组件可能需要被释放 (如它们实现 idisposable)-Autofac 可以在释放生存期范围时处理这些组件。

但是, 容器在应用程序的生存期内。如果你直接从容器中解决了很多东西, 你可能会有很多东西挂在等待处置。这不太好 (您可能会看到 "内存泄漏" 这样做)。

而是从容器创建子生存期范围并从此解决。当您完成了解析组件后, 处置子范围, 一切都将为您清理。

(当您使用 Autofac 集成库时, 此子范围创建主要是为您完成的, 因此您不必考虑它。

对于我们的示例应用程序, 我们将实现 "WriteDate" 方法, 以使编写器从范围中得到, 并在完成后处理该范围。

namespace DemoApp
{
  public class Program
  {
    private static IContainer Container { get; set; }
    static void Main(string[] args)
    {
      // ...the stuff you saw earlier...
    }
    public static void WriteDate()
    {
      // Create the scope, resolve your IDateWriter,
      // use it, then dispose of the scope.
      using (var scope = Container.BeginLifetimeScope())
      {
        var writer = scope.Resolve<IDateWriter>();
        writer.WriteDate();
      }
    }
  }
}

现在当你运行你的程序...


“WriteDate”方法向Autofac询问IDateWriter。

Autofac看到IDateWriter映射到TodayWriter,所以开始创建一个TodayWriter。

Autofac认为TodayWriter在其构造函数中需要一个IOutput。

Autofac看到IOutput映射到ConsoleOutput,所以创建一个新的ConsoleOutput实例。

Autofac使用新的ConsoleOutput实例来完成TodayWriter的构建。

Autofac将“WriteDate”的完全构建的TodayWriter返回给消费者。

之后,如果您希望应用程序编写不同的日期,则可以实现不同的IDateWriter,然后在应用程序启动时更改注册。你不必改变任何其他类。 这样就实现了反转控制!

注意:一般来说,服务位置在很大程度上被认为是反模式(见文章)。也就是说,手动创建范围无处不在,并通过代码散布使用容器不一定是最好的方法。使用Autofac集成库,您通常不需要在上面的示例应用程序中执行。相反,事情从应用程序的中央“顶级”位置解决,手动解析很少见。当然,您如何设计您的应用程序取决于您。



更多资料

示例应用程序让您了解如何使用Autofac,但还有更多的可以做。

查看集成库列表,了解如何将Autofac与应用程序集成。

了解如何注册增加灵活性的组件。

了解Autofac配置选项,让您更好地管理组件注册。



寻求帮助?

您可以在StackOverflow上提问。

您可以参加Autofac Google Group。

CodeProject有一个介绍性的Autofac教程。

如果您想深入深入,我们会提供高级调试技巧。

源代码以及Visual Studio项目文件可在GitHub上找到。 有关贡献的构建说明和详细信息,请参阅“贡献者指南”。


版权声明:本站所有教程均为本站原创或翻译,转载请注明出处,请尊重他人劳动果实。请记住本站地址:www.yuanjiaocheng.net (猿教程) 作者:卿文刚
本文标题: C#环境
本文地址:http://www.yuanjiaocheng.net/Autofac/autofac-example.html