在 .net core 2.1 和 3.1 中使用 autofac

通过本文你可以获得如何用 autofac 替换 .NET CORE(2.1,3.1) 默认 IOC 容器。

生命周期说明

  • 每个依赖一个实例(Instance Per Dependency) (默认) —-InstancePerDependency()
  • 单一实例(Single Instance) 单例 —-SingleInstance()
  • 每个生命周期作用域一个实例(Instance Per Lifetime Scope)—-InstancePerLifetimeScope()
  • 每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)—-InstancePerMatchingLifetimeScope()
  • 每个请求一个实例(Instance Per Request) asp.net web请求—-InstancePerRequest()
  • 每次被拥有一个实例(Instance Per Owned) —-InstancePerOwned()

注册方式

  • 反射
  • 使用实例
  • lambda 表达式

示例代码说明:

// 创建注册组件的builder
var builder = new ContainerBuilder();

//根据类型注册组件 ConsoleLogger 暴漏服务:ILogger
builder.RegisterType<ConsoleLogger>().As<ILogger>();

//根据类型注册组件 ConsoleLogger,暴漏其实现的所有服务(接口)
builder.RegisterType<ConsoleLogger>().AsImplementedInterfaces();

// 根据实例注册组件 output  暴漏服务:TextWriter
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();

//表达式注册组件,这里我们是在构造函数时传参->"musection"   暴漏服务:IConfigReader
builder.Register(c =new ConfigReader("mysection")).As<IConfigReader>();

//表达式注册组件,解析时传参
var service = scope.Resolve<IConfigReader>(
           new NamedParameter("section", "mysection"));     

//反射注册组件,直接注册了ConsoleLogger类(必须是具体的类),如果ConsoleLogger有多个构造函数,将会取参数最多的那个构造函数进行实例化
builder.RegisterType<ConsoleLogger>();

//反射注册组件,手动指定构造函数,这里指定了调用 MyComponent(ILogger log,IConfigReader config)的构造函数进行注册
builder.RegisterType<MyComponent>()
 .UsingConstructor(typeof(ILogger), typeof(IConfigReader));  

 //注册MySingleton类中的静态变量"Instance",ExternallyOwned()函数指定自己控制实例的生命周期,而不是由autofac自动释放
 builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();

//一个组件暴漏两个服务  
builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>(); 

//注册当前程序集中以“Service”结尾的类
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
//注册"MyApp.Repository"程序集中所有的类
builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();

//构建一个容器完成注册
var rootcontainer = builder.Build();

//可以通过下面这种方式手动获取IConfigReader 的实现类
//这种手动解析的方式需要 从生命周期作用域内获取组件,以保证组件最终被释放
//不要直接从根容器rootcontainer中解析组件,很有可能会导致内存泄漏
using(var scope = rootcontainer.BeginLifetimeScope())
{
  var reader = scope.Resolve<IConfigReader>();
}

在 ASP.NET CORE 2.1 中的使用

.NET CORE 2.2 和 3.1 对 Autofac 的初始化方式不一样,需要注意下,建议使用 3.1。

需要安装一下的库:

IocPolicy.cs

public class IocPolicy : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        //注册当前程序集中以“Ser”结尾的类,暴漏类实现的所有接口,生命周期为PerLifetimeScope
        builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().SingleInstance();
        //注册所有"MyApp.Repository"程序集中的类
        //builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
    }
}

接管默认 IoC 引擎

需要修改 Startup.cs,需要调整 ConfigServices 方法签名,以让 autofac 接管 ioc

public static IContainer AutofacContainer;
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            #region >>AutoFac  1/2
            ContainerBuilder builder = new ContainerBuilder();
            //将services中的服务填充到Autofac中.
            builder.Populate(services);
            //新模块组件注册
            builder.RegisterModule<Application.IocPolicy>();
            builder.RegisterModule<Domain.IocPolicy>();
            //创建容器.
            AutofacContainer = builder.Build();
            //使用容器创建 AutofacServiceProvider 
            return new AutofacServiceProvider(AutofacContainer);
            #endregion
        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
             #region >>AutoFac  2/2
            //程序停止调用函数
            appLifetime.ApplicationStopped.Register(() => { AutofacContainer.Dispose(); });
            #endregion
        }

在 ASP.NET CORE 3.1 中的使用

这里跟 core 2.2不一样,更加偏向于默认的 IoC 容器了,也方便了不少。

需要安装以下的库:

IocPolicy.cs

public static class IocPolicy
{
    public static void RegisterApplication(this ContainerBuilder builder)
    {
        //注册当前程序集中以“Ser”结尾的类,暴漏类实现的所有接口,生命周期为PerLifetimeScope
        builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().SingleInstance();
        //注册所有"MyApp.Repository"程序集中的类
        //builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
    }
}

接管默认 IoC 引擎

需要修改 Startup.cs,需要调整 ConfigServices 方法签名,以让 autofac 接管 ioc

/* 新增加如下方法,用于注册类型 */

        public void ConfigureContainer(ContainerBuilder builder)
        {
            #region >>AutoFac
            builder.RegisterApplication();
            builder.RegisterDomain();
            #endregion
        }

Program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //autofac 接管
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });