• autofac 注册


    1 注册的概念和方式

      使用autofac 的ContainerBuilder 来注册组件(components---通常指实现类),并把它的服务(service---通常指接口,抽象类,类实例)暴露给调用方。

      autofac 通过相似的 Register() 方法来进行注册,通过As() 方法来公开服务

      1) 创建一个ContainerBuilder 来注册组件和服务

     var builder = new ContainerBuilder();

      2)  通过反射类型来进行注册 。

    builder.RegisterType<ConsoleLogger>.As<ILogger>();

      3)  通过一个实例来进行注册

    var output = new StringWriter();
    builder.RegisterInstance(output).As<TextWriter>();

       如果用实例来注册,每次解析时,获得结果都是同一个实例。

    builder.RegisterInstance(MyInstance.Instance).ExternallyOwned();  
    ExternallyOwned() 方法配置组件不会被释放。

      4) 通过Lamda表达式的方式来构建注册

    // Register expressions that execute to create objects...
    builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();

      5) 通过RegisterGeneric()方法 支持泛型接口注册

    //注册
    builder.RegisterGeneric(typeof(List<>))
           .As(typeof(IList<>))
           .InstancePerLifetimeScope();
    //解析代码
    var tasks = container.Resolve<IList<String>>();

        容器会自动根据传递的 T 类型 进行解析 

    6) 通过程序集进行注册

    // 通过程序集进行注册
       builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();

    以上代码AsImplementedInterfaces() 方法 会把当前运行的程序集中所有实现了接口的组件进行注册,并把接口作为服务对外公开。

    例如: 程序集中包含了 2个接口:IOutput 和 IDateWriter

               和三个实现类:class ConsoleOutput : IOutput

                                  class CurentDateWriter :IDateWriter

                          class MyComponent:IOutput,IDateWriter

    那么这三个都会被注册。如果程序集中还有其他类型实现了接口,也会被自动注册,除了 IDisposable 接口

    7) 通过链式语法把一个组件注册为多个服务对外公开

    // 链式注册
    builder.RegisterType<MyComponent>()
           .AsSelf()    // 公开MyComponent 的实例
           .As<IOutput>()   // 公开IOutput 的 实例
           .As<IDataWriter>();    // 公开 IDataWriter 的实例
    

    所以如下三种解析都可以正常工作

     
    // 都可以正常执行
    scope.Resolve<IOutput>();
    scope.Resolve<IDataWriter>();
    scope.Resolve<MyComponent>();

    2  条件注册

    1) 注册时添加筛选条件

      示例1:在程序集中,通过Where() 筛选名称以“Repository” 结尾的类进行注册,并制定服务进行公开

    // asm 为一个程序集变量
    builder.RegisterAssemblyTypes(asm)
           .Where(t => t.Name.EndsWith("Repository"))
           .As<IRepository>();

    通过Where 提供Lamda 集合操作,可以对类进行筛选。

      示例2 : 通过 Except() 方法排除不需要注册的类

    //  排除 MyUnwantedType 不注册
    builder.RegisterAssemblyTypes(asm)
           .Except<MyUnwantedType>();

    3  Autofac 构造函数注册

      1)  当组件类有多个构造函数,通过RegisterType 方法注册的组件后,解析服务时,会通过反射形式,根据构造函数参数从多到少的方式匹配。

    // 多构造函数组件   
     public class MyComponent
        {
            public string Name {get;set;}
            public MyComponent() { Name = "no parameter"; }
            public MyComponent(IOutput output) { Name = string.Format("parameter is {0}", output.ToString()); }
            public MyComponent(IOutput output, IDateWriter writer) { Name = string.Format("parameter is {0} and {1}", output.ToString(),writer.ToString()); }
        }
    
     class Program
        {
            static IContainer container { get; set; }
            static void Main(string[] args)
            {
                var builder = new ContainerBuilder();
    
                // 注册类型,通过反射注册
                builder.RegisterType<MyComponent>();
                builder.RegisterType<ConsoleOutput>().As<IOutput>();
    
                container = builder.Build();  //构建容器
    
                //使用
                using (var scope = container.BeginLifetimeScope())
                {
                    var component = container.Resolve<MyComponent>();
                    Console.WriteLine(component.GetType());
                    Console.WriteLine(component.Name);
                }           
                
                Console.ReadKey();
            }
        }
    •   Autofac 根据上诉代码,在解析MyComponent 时,会先看容器中,是否有已注册的 ILoger 和IConfigReader 的 服务
    •   Autofac 发现只有一个ILoger 服务,而没有 IConfigReader 的服务,于是自动选择 带一个ILoger 构造参数的 构造函数实例化 M

    运行结果:

    image

    2) 通过UsingConstructor()指定构造函数注册

    builder.RegisterType<MyComponent>()
           .UsingConstructor(typeof(ILogger), typeof(IDataWriter));
    • 当容器中,存在ILoger 和IDataWriter  的 注册时,当Resolve<MyComponent> 时,容器会返回2个构造函数的实例
    • 当容器中,只存在Iloger  的注册时,因为是手动用2个构造函数进行祖册,此时Resolve<MyComponent> 会抛出异常,因为IDataWriter 的注册实例不存在。

    4 Autofac 自动解析规则

       1) 如果有多个组件注册,并以同一个服务对外公开,autofac 会取最后一个最后一个注册的组件,作为服务

    builder.Register<ConsoleLogger>().As<ILogger>();
    builder.Register<FileLogger>().As<ILogger>();

      以上注册代码,FileLogger 组件会被默认公开,因为它是最后一个注册为ILogger 的服务。

    5 为注册组件传递参数

      下面有一个读取配置节点值的 类

    public class ConfigReader : IConfigReader
    {
      public ConfigReader(string configSectionName)
      {
        // Store config section name
      }
    
      // ...read configuration based on the section name.
    }

    1 )  通过Lamda表达式 传递参数

    builder.Register(c => new ConfigReader("sectionName")).As<IConfigReader>();

    “sectionName” 就是传递节点名称的值。

    2 ) 通过方法WithParameters 传递参数

    // Using a NAMED parameter:
    builder.RegisterType<ConfigReader>()
           .As<IConfigReader>()
           .WithParameter("configSectionName", "sectionName");
    
    // Using a TYPED parameter:
    builder.RegisterType<ConfigReader>()
           .As<IConfigReader>()
           .WithParameter(new TypedParameter(typeof(string), "sectionName"));
    
    // Using a RESOLVED parameter:
    builder.RegisterType<ConfigReader>()
           .As<IConfigReader>()
           .WithParameter(
             new ResolvedParameter(
               (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
               (pi, ctx) => "sectionName"));
  • 相关阅读:
    Apache Shiro和Spring Security的详细对比
    Oauth2.0 用Spring-security-oauth2 来实现
    引入AOP 报错 error at ::0 formal unbound in pointcut
    日记网站收藏
    Spring 在web 容器中的启动过程
    knockoutjs如何动态加载外部的file作为component中的template数据源
    ORACLE触发器详解
    浅谈数据库分表
    HTTP协议详解(真的很经典)
    ThinkPHP的四种URL模式 URL_MODEL
  • 原文地址:https://www.cnblogs.com/iampkm/p/4767149.html
Copyright © 2020-2023  润新知