写点什么

在 ASP.NET Core 引入 Autofac 增强容器

作者:雄鹿 @
  • 2024-03-26
    广东
  • 本文字数:2581 字

    阅读完需:约 8 分钟

在 ASP.NET Core 引入 Autofac 增强容器

本文章介绍在 ASP.NET Core 中引入 Autofac 来增强容器能力

先决条件

.NET 8 SDK

介绍

Autofac 提供了一种灵活和可扩展的方式来管理对象的生命周期、解决依赖关系以及进行属性注入

Autofac 有一些强大的功能,例如

  1. 基于名称的注入 - 按照名称来区分它不同的实现的时候

  2. 属性注入 - 直接把服务注册到某一个类的属性中

  3. 子容器

  4. 基于动态代理的 AOP

用 Autofac 覆盖默认的 Ioc

在引入 Autofac Nuget 包后

在 Program 中注册 Autofac ,使用 UseServiceProviderFactory 方法

    public static IHostBuilder CreateHostBuilder(string[] args) =>        Host.CreateDefaultBuilder(args)        	// 重写用于创建服务提供程序的工厂        	// 把AutofacServiceProviderFactory注册进去            .UseServiceProviderFactory(new AutofacServiceProviderFactory())            .ConfigureWebHostDefaults(webBuilder =>            {                webBuilder.UseStartup<Startup>();            });
复制代码


然后在 Startup 中添加一个 ConfigureContainer 方法

原本存在的 ConfigureServices 方法是注入默认的容器

服务注册进默认的容器以后会被 Autofac 接替

然后执行 ConfigureContainer 方法

使用方式

用 Autofac 覆盖默认的 Ioc 后

普通注册

使用 Autofac 的注册方式和 默认的 Ioc 框架注册方式略有不同

	public void ConfigureContainer(ContainerBuilder builder)    {    	// 先注册具体实现,然后是标记为哪个服务类型		builder.RegisterType<T>().As<IT>();	}
复制代码


使用时

	public void Configure(IApplicationBuilder app)	{		// 也可以直接在构造函数中请求 ILifetimeScope  		ILifetimeScope AutofacContainer = app.ApplicationServices.GetAutofacRoot();		IT t = AutofacContainer.Resolve<IT>();	}
复制代码

基于名称注册

当我们需要将一个服务注册多次,并用不同命名来区分时

	public void ConfigureContainer(ContainerBuilder builder)    {    	// 使用Named		builder.RegisterType<T>().Named<IT>("service2");	}
复制代码


使用时

	public void Configure(IApplicationBuilder app)	{		// 也可以直接在构造函数中请求 ILifetimeScope  		ILifetimeScope AutofacContainer = app.ApplicationServices.GetAutofacRoot();		IT t = AutofacContainer.ResolveNamed<IT>("service2")	}
复制代码

属性注入

属性注入使用 PropertiesAutowired 方法

	#region Class	public class T: IT    {        public Attribute Attr { get; set; }    }    	public class Attribute { }	#endregion		public void ConfigureContainer(ContainerBuilder builder)    {    	// 属性注入    	builder.RegisterType<Attribute>();		builder.RegisterType<T>().As<IT>().PropertiesAutowired()	}
复制代码


使用时 Attr 属性不为 NULL

	public void Configure(IApplicationBuilder app)	{		// 也可以直接在构造函数中请求 ILifetimeScope  		ILifetimeScope AutofacContainer = app.ApplicationServices.GetAutofacRoot();		// t 的 Attr 属性不为 null		IT t = AutofacContainer.Resolve<IT>();	}
复制代码

AOP

我们在不期望改变原有类的情况下,在方法执行时嵌入一下逻辑

让我们可以在方法执行的切面上任意插入我们的逻辑

	#region Class	public class MyInterceptor : IInterceptor    {        public void Intercept(IInvocation invocation)        {            Console.WriteLine($"intercept before");i            // 不执行该语句 就不执行原有的方法            invocation.Proceed();            Console.WriteLine($"intercept after");        }    }
public class T: IT { public void Write() { Console.WriteLine($"T_Write()"); } } #endregion
public void ConfigureContainer(ContainerBuilder builder) { #region AOP // 注册拦截器到容器中 builder.RegisterType<MyInterceptor>(); // builder.RegisterType<MyNameService>(); builder.RegisterType<T>().As<IT>() // 允许属性注册 .PropertiesAutowired() // 指定拦截器 .InterceptedBy(typeof(MyInterceptor)) // 实现接口拦截器 // (如果用类拦截器,方法需要设置为虚方法,允许继承类重载的情况下,才可以拦截到具体方法) .EnableInterfaceInterceptors(); #endregion }
复制代码


使用时

	public void Configure(IApplicationBuilder app)	{		// 也可以直接在构造函数中请求 ILifetimeScope  		ILifetimeScope AutofacContainer = app.ApplicationServices.GetAutofacRoot();		// t 的 Attr 属性不为 null		IT t = AutofacContainer.Resolve<IT>();		// 可以看到方法的执行顺序		t.Write();	}
复制代码

子容器

Autofac 具备给子容器命名的特性

    public void ConfigureContainer(ContainerBuilder builder)    {        #region 子容器        builder.RegisterType<T>()            // 将一个服务注入到特定命名为 myscope 的子容器中            .InstancePerMatchingLifetimeScope("myscope");        #endregion    }
复制代码


使用时

	public void Configure(IApplicationBuilder app)	{		// 也可以直接在构造函数中请求 ILifetimeScope  		ILifetimeScope AutofacContainer = app.ApplicationServices.GetAutofacRoot();        #region 子容器        // 创建了一个叫 myscope 的子容器        using (var myscope = AutofacContainer.BeginLifetimeScope("myscope"))        {            var t1= myscope.Resolve<T>();            using (var scope = myscope.BeginLifetimeScope())            {                var t2= scope.Resolve<T>();                var t3= scope.Resolve<T>();                // 得到的都是同一个对象                var co1 = t1 == t2; // true                var co2 = t1 == t3; // true            }        }        #endregion	}
复制代码


当我们不期望对象在根容器创建时,

又希望它在某一定范围内是单例模式的情况下,可以使用 子容器

参考文档

用Autofac增强容器能力 - 肖伟宇

发布于: 刚刚阅读数: 2
用户头像

雄鹿 @

关注

心像开满花的树。 2019-01-04 加入

一名全栈开发工程师,热爱编程,对新技术充满好奇心,专注于使用ASP.NET Core和Angular进行Web应用的开发。

评论

发布
暂无评论
在 ASP.NET Core 引入 Autofac 增强容器_ASP.NET Core_雄鹿 @_InfoQ写作社区