Skip to content

第三方 DI 容器 Autofac 与 AOP #41

@Henrik-Xu

Description

@Henrik-Xu

第三方 DI 容器 AutofacAOP

Autofac 是什么

这个是一种老牌的 Ioc 容器,很多大型项目都在使用,轻量级,而且性能很高。

为什么使用 Autofac 而不是系统内置容器

系统内置容器一般只支持构造方法注入,不支持名称注入,属性注入,AOP 等。

Autofac 使用

  1. Autofac 为什么可以替换 .NetCore 内置容器

UseServiceProviderFactory<TContainerBuilder> 需要传递一个( IServiceProviderFactory<TContainerBuilder>

接口实现类

IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);

Autofac 实现了 public class AutofacServiceProviderFactory : IServiceProviderFactory<ContainerBuilder>

即接口多态的使用。

  1. Nuget 引入 Autofac

Autofac.Extensions.DependencyInjection

Autofact.DynamicProxy

  1. Program.cs 中注册第三方容器
public static IHostBuilder CreateHostBuilder(string[] args) =>
          Host.CreateDefaultBuilder(args)
              //注册第三方容器
              .UseServiceProviderFactory(new AutofacServiceProviderFactory())
              .ConfigureWebHostDefaults(webBuilder =>
              {
                  webBuilder.UseStartup<Startup>();                  
              })
  1. Startup 中添加新的服务注册方法

只要方法正确添加,即可完整的无缝和前面的内置框架集成。

Startup 类中服务注册:

using Autofac.Extras.DynamicProxy;
// 系统内置的方法,无需改变
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    //注入我们自己需要的服务
    //services.AddTransient<IServiceA, ObjectA>(); 
    //services.AddSingleton<IServiceB, ObjectB>();  
    //services.AddScoped<IServiceC, ObjectC>();    
    services.AddTransient<IServiceD, ObjectD>();
}

// Autofac 注册服务
public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterType<ObjectA>().As<IServiceA>().InstancePerDependency();
    builder.RegisterType<ObjectB>().As<IServiceB>().SingleInstance();
    builder.RegisterType<ObjectC>().As<IServiceC>().InstancePerLifetimeScope();
}

服务 Provider: 跟之前一样,无需改变,实现无缝集成。

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly ILoggerFactory _loggerFactory;
    private readonly IServiceA _serviceA;
    private readonly IServiceB _serviceB;
    private readonly IServiceC _serviceC;
    public HomeController(ILogger<HomeController> logger,ILoggerFactory loggerFactory,
        IServiceA serviceA, IServiceB serviceB, IServiceC serviceC)
    {
        _logger = logger;
        _loggerFactory = loggerFactory;
        this._serviceA = serviceA;
        this._serviceB = serviceB;
        this._serviceC = serviceC; 
    }
  

    public IActionResult Index()
    {
        this._serviceA.Operation();
        this._serviceB.Operation();
        this._serviceC.Operation();

        this._loggerFactory.CreateLogger<HomeController>().LogInformation("这个是 this._loggerFactory.LogInformation的输出!");
        this._loggerFactory.CreateLogger<HomeController>().LogWarning("这个是 this._loggerFactory.LogWarning!");
        this._loggerFactory.CreateLogger<HomeController>().LogError("这个是 this._loggerFactory.LogError!");

        return View();
    }
}

Autofac 中使用 AOP

模型

--------------------
--------------------

课堂订单提交业务

--------------------
--------------------
  1. 定义接口,实现接口
/// <summary>
/// 核心业务接口
/// </summary>
public interface IMyStudy
{
    void StudyNetCore(string content);
}

public class MyStudy : IMyStudy
{
    public void StudyNetCore(string content)
    {
        //实际开发中,应该在这个地方写具体的实现

        Console.WriteLine($"我们现在开始学习:{content}");


    }

    //扩展1...

    //扩展2...
}
  1. 扩展业务,实现拦截器接口,并在原有业务类中,增加拦截器接口特性
using Castle.DynamicProxy;
public class MyStudyAOP : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("预习...");

        invocation.Proceed();//调用核心的业务

        Console.WriteLine("巩固...");
    }
}

/// <summary>
/// 核心业务接口添加拦截器
/// </summary>
public interface IMyStudy
{
    void StudyNetCore(string content);
}

[Intercept(typeof(MyStudyAOP))]  //通过特性拦截器扩展的业务
public class MyStudy : IMyStudy
{
    public void StudyNetCore(string content)
    {
        //实际开发中,应该在这个地方写具体的实现

        Console.WriteLine($"我们现在开始学习:{content}");


    }
}
  1. 服务注册

Startup 类中注册服务

using Autofac.Extras.DynamicProxy;
public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterType<ObjectA>().As<IServiceA>().InstancePerDependency();
    builder.RegisterType<ObjectB>().As<IServiceB>().SingleInstance();
    builder.RegisterType<ObjectC>().As<IServiceC>().InstancePerLifetimeScope();

    //注册扩展业务类
    builder.Register(c => new MyStudyAOP());

    //注册核心业务类,并开启接口拦截器
    builder.RegisterType<MyStudy>().As<IMyStudy>().EnableInterfaceInterceptors();
}

问题:随着业务越来越复杂,注册的服务越来越多,代码越来越复杂

解决:独立自定义一个容器注册类,重写 Load 方法,完成服务注册,和扩展业务注册

using Autofac;
using Autofac.Extras.DynamicProxy
public class CustomAutofacModule:Autofac.Module
{
    //重写Load方法
    protected override void Load(ContainerBuilder containerBuilder)
    {
        var assembly = this.GetType().GetTypeInfo().Assembly;
        var builder = new ContainerBuilder();
        var manager = new ApplicationPartManager();
        manager.ApplicationParts.Add(new AssemblyPart(assembly));
        manager.FeatureProviders.Add(new ControllerFeatureProvider());
        var feature = new ControllerFeature();
        manager.PopulateFeature(feature);


        //注册我们自己需要的各种服务
        containerBuilder.RegisterType<ObjectA>().As<IServiceA>().InstancePerDependency();
        containerBuilder.RegisterType<ObjectB>().As<IServiceB>().SingleInstance();
        containerBuilder.RegisterType<ObjectC>().As<IServiceC>().InstancePerLifetimeScope();

    
        //注册扩展业务类
        containerBuilder.Register(c => new MyStudyAOP());

        //注册核心业务类,并开启接口拦截器
        containerBuilder.RegisterType<MyStudy>().As<IMyStudy>().EnableInterfaceInterceptors();
    }
}

修改注册服务:

using Autofac.Extras.DynamicProxy;
public void ConfigureContainer(ContainerBuilder builder)
{
    //使用模块化集中注册服务的方式
    builder.RegisterModule<CustomAutofacModule>();
}

服务调用:

 public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly ILoggerFactory _loggerFactory;
        private readonly IServiceA _serviceA;
        private readonly IServiceB _serviceB;
        private readonly IServiceC _serviceC;

        private readonly IMyStudy _imyStudy;


        public HomeController(ILogger<HomeController> logger,ILoggerFactory loggerFactory,
            IServiceA serviceA, IServiceB serviceB, IServiceC serviceC,IMyStudy imyStudy)
        {
            _logger = logger;
            _loggerFactory = loggerFactory;
            this._serviceA = serviceA;
            this._serviceB = serviceB;
            this._serviceC = serviceC;

            this._imyStudy = imyStudy;
        }
        public IActionResult Index()
        {
            this._imyStudy.StudyNetCore("依赖注入容器DI和AOP!");

            return View();
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions