注册组件

通过容器构造器ContainerBuilder注册组件的三种方式:

  1. 通过类型反射注册

  2. 通过现存实例注册(实现对象的实例)

  3. lambda表达式注册(通过可实例化对象的匿名函数注册)

每个组件可暴露一个或多个服务,通过ContainerBuilder中的As()方法组装

// 创建注册组件/服务的构建器。
var builder = new ContainerBuilder();
​
// 通过类型反射注册
builder.RegisterType<ConsoleLogger>().As<ILogger>();
​
// 通过实例对象注册
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
​
// 通过创建实例对象的lambda表达式注册
builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();
// 通过容器构造器ContainerBuilder创建容器
// 准备对象解析
var container = builder.Build();
​
// 你现在可以通过 Autofac去解析服务.比如,
//此行代码将解析并获取(执行注册的lambda表达式注册的那个)服务的依赖实例reader
using(var scope = container.BeginLifetimeScope())
{
  var reader = scope.Resolve<IConfigReader>();
}

 

 

反射组件

按类型注册

通过反射生成的组件通常按类型注册

 

//创建容器生成器
var builder = new ContainerBuilder();
//通过反射注册的两种写法
builder.RegisterType<ConsoleLogger>();
builder.RegisterType(typeof(ConfigReader));

 

当使用基于反射的组件时,Autofac 会自动为您的类使用构造函数,其中包含能够从容器中获取的最多参数

例如,假设您有一个包含三个构造函数的类,如下所示:

public class MyComponent
    {
        public MyComponent() { Console.WriteLine("无参构造方法被调用"); }
        public MyComponent(InterfaceTestA testA) { Console.WriteLine("第一个方法A被调用"); }
        public MyComponent(InterfaceTestA testA, InterfaceTestB testB) { Console.WriteLine("方法A、B都被调用"); }
        public void test()
        {
            Console.WriteLine("方法Test被调用");
        }
    }

 

 

现在假设您在容器中注册组件和服务,如下所示:

 static void Main(string[] args)
        {
            var build = new ContainerBuilder();
            build.RegisterType<EntityImpA>().As<InterfaceTestA>();
            build.RegisterType<EntityImpB>().As<InterfaceTestB>();
            build.RegisterType<MyComponent>();
            Console.WriteLine("Hello World!");
            var containner = build.Build();
            using (var scope = containner.BeginLifetimeScope())
            {
                //用生命周期作用域解析获取IDateWriter对应的依赖对象实例
                var writer = scope.Resolve<MyComponent>();
                writer.test();
            }
        }

 

当您解析您的组件cope.Resolve<MyComponent>()时,Autofac 将看到您已EntityImpA、EntityImpB注册,在这种情况下,将选择第三个构造函数

public MyComponent(InterfaceTestA testA, InterfaceTestB testB) { Console.WriteLine("方法A、B都被调用"); }

 

假设您在容器中注册组件和服务,如下所示:

 static void Main(string[] args)
        {
            var build = new ContainerBuilder();
            build.RegisterType<EntityImpA>().As<InterfaceTestA>();
            //build.RegisterType<EntityImpB>().As<InterfaceTestB>();
            build.RegisterType<MyComponent>();
            Console.WriteLine("Hello World!");
            var containner = build.Build();
            using (var scope = containner.BeginLifetimeScope())
            {
                //用生命周期作用域解析获取IDateWriter对应的依赖对象实例
                var writer = scope.Resolve<MyComponent>();
                writer.test();
            }
        }

当您解析您的组件cope.Resolve<MyComponent>()时,Autofac 将看到您已EntityImpA注册,EntityImpB没注册在这种情况下,将选择第二个构造函数

public MyComponent(InterfaceTestA testA) { Console.WriteLine("第一个方法A被调用");因为它是容器中可以找到的参数最多的构造函数。

 

 

 

 

基于反射的组件的重要说明:您注册的任何组件类型都RegisterType必须是具体类型

指定构造函数

也可以通过一个特定的构造函数来使用和重写这种自动选择的构造方法,通过UsingConstructor方法和一系列表示构造函数中参数类型的参数列表注册你的组件

builder.RegisterType<MyComponent>()
      .UsingConstructor(typeof(ILogger), typeof(IConfigReader));

请注意,您仍需要在解析时提供必要的参数,否则在尝试解析对象时会出现错误。您可以在注册时传递参数,也可以在解析时传递参数。

此时解析时会走的构造方法是public MyComponent(ILogger logger, IConfigReader reader) { /* ... */ }