第三节 最简单最清晰的AutoFac的demo

这一节是通过官网的Getting Started的demo加工简化而来,为了单纯说明这个框架的最核心的功能,去掉接口,在Console Application中演示,有兴趣可以看官网原版 —— [ AutoFac Home ]

安装

支持NuGet便捷安装

第三节 最简单最清晰的AutoFac的demo_第1张图片

构建需求环境

需求环境1-打印模块

using System;

namespace Demo
{
      public class ConsoleOutput
      {
            public void Write(string content)
            {
              Console.WriteLine(content);
            }
      }
}

需求环境2-打印内容模块

using System;

namespace Demo
{
      public class TodayWriter
      {
            private ConsoleOutput _output;

            public TodayWriter(ConsoleOutput output)
            {
              this._output = output;
            }

            public void WriteDate()
            {
              this._output.Write(DateTime.Now.ToString());
            }
      }
}

使用AutoFac

Code

namespace Demo
{
      public class Program
      {
            static void Main(string[] args)
            {
                //①
                var builder = new ContainerBuilder();
                //②
                builder.RegisterType();
                //③
                builder.RegisterType();
                //④
                var container = builder.Build();

                //⑤
                var writer = container.Resolve();
                //⑥
                writer.WriteDate();

            }
      }
}

结果

这里写图片描述

三个疑惑

需求上,想要创建TodayWriter对象,并将ConsoleOutput对象以构造的方式传入,打印当前的时间。

在Main中,方便解析,给每一行代码做了一个编号。运行Main方法后,功能成功了!

分析代码,⑥执行打印,很好理解,pass。
⑤创建了TodayWriter对象,但是writer对象是怎么创建的,没有看到new啊
打印成功了,write对象里面肯定有ConsoleOutput对象的引用,怎么来的,没看到传递呀
TodayWriter对象我有指定参数构造,那就不会有无参构造,再次印证writer对象是必须传ConsoleOutput对象的引用的,依赖的ConsoleOutput对象没看到创建呀

解析

① ContainerBuilder是AutoFac框架提供的容器。理解为一个盒子,当new这个容器的时候,就是找了一个盒子并打开了盖子。

②③ builder.RegisterType,注册服务,将想要暴露的对象以这种语法进行注册。理解为往盒子中装东西。暴露的对象理解为外部需要的,TodayWriter对象需要ConsoleOutput对象,我们注册了ConsoleOutput对象;Mai’n中需要TodayWriter对象,我们注册了TodayWriter对象。

④builder.Build()容器构建完成。将盒子的盖子盖上。

官方解释上面三个疑问:

  • WriteDate方法向Autofac请求需要一个TodayWriter对象
  • Autofac看到TodayWriter对象已经注册
  • Autofac看到TodayWriter的构造依赖ConsoleOutput对象
  • Autofac看到ConsoleOutput对象已经注册
  • Autofac创建了一个ConsoleOutput对象
  • Autofac使用新创建的ConsoleOutput对象创建了一个TodayWriter对象
  • Autofac创建完成TodayWriter对象后,将引用返回

总结

由上面例子可以看出AutoFac这款框架用来解决上一节学到的IOC控制反转和DI依赖注入。

IOC的定义中,将依赖的对象获得交给第三方系统来控制,在这里AutoFac就承担了这个角色。

Remarks

将注册的过程理解为盒子,这种理解方式贴近使用代码的流程,打开盒盖,放东西,盖上盖子。分析代码可见,builder.Build()这一步才真正的创建了容器。

// Summary:
// Create a new container with the component registrations that have been made.
//
// Parameters:
// options:
// Options that influence the way the container is initialised.
//
// Returns:
// A new container with the configured component registrations.
//
// Remarks:
// Build can only be called once per Autofac.ContainerBuilder - this prevents ownership
// issues for provided instances. Build enables support for the relationship types
// that come with Autofac (e.g. Func, Owned, Meta, Lazy, IEnumerable.) To exclude
// support for these types, first create the container, then call Update() on the
// builder.
public IContainer Build(ContainerBuildOptions options = ContainerBuildOptions.None);

AutoFac创建对象的性能是和new一样的。

When you resolve a component, depending on the instance scope you define, a new instance of the object gets created. (Resolving a component is roughly equivalent to calling “new” to instantiate a class. That’s really, really oversimplifying it, but from an analogy perspective it’s fine.)

官网解释中,是由WriteDate方法向Autofac请求需要一个TodayWriter对象这样逆推的流程,如果将环境改成如下,新增加一个打印模块并注册进容器中,调用WriteData方法,发现AutoFac没有去实例化无效依赖的对象。

using System;

namespace Demo
{
     //新增一个打印模块
      public class ConsoleOutput2
      {
            public void Write(string content)
            {
              Console.WriteLine(content);
            }
      }

      public class TodayWriter
      {
            private ConsoleOutput _output;
            private ConsoleOutput2 _output2;

            public TodayWriter(ConsoleOutput output)
            {
              this._output = output;
            }

            //新增一个构造,多依赖一个对象
            public TodayWriter(ConsoleOutput2 output)
            {
              this._output2 = output;
            }

            public void WriteDate()
            {
              this._output.Write(DateTime.Now.ToString());
            }
      }
}

第三节 最简单最清晰的AutoFac的demo_第2张图片

你可能感兴趣的:(Major:AutoFac,AutoFac)