AutoFac注册的动态实例 Named和Keyed
named和keyed是有多个实现时,应用程序根据不同参数或不同场景下进行选择性实例。(我理解是这样的,能想到的场景:支付(根据用户选择实例 支付宝或微信))
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AdminWebApi.IServices; using AdminWebApi.Service; using Autofac; namespace AdminWebApi.Autofac { public class AutofacMoule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly())//注册整个程序集 .Where(n => n.Name.EndsWith("Service")).AsImplementedInterfaces()//注册程序集内以Service结尾的文件 .SingleInstance();//单例模式 //.InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()) .Where(n => n.Name.EndsWith("Repository")).AsImplementedInterfaces()//注册程序集内以Repository结尾的文件 .SingleInstance(); builder.RegisterTypeAutofacModule().As ().SingleInstance(); builder.RegisterType ().Named ("two").As ().InstancePerDependency(); builder.RegisterType ().Named ("one").As ().InstancePerDependency(); builder.RegisterType ().Keyed (keyid.one).As ().InstancePerDependency(); builder.RegisterType ().Keyed (keyid.two).As ().InstancePerDependency(); } } public enum keyid { one = 1, two = 2 } }
这里是注册代码的截图与AutofacModule代码,用不同颜色框标识了named 和keyed。(黄色是固定注册;蓝色是同时注册了两个不同的实现,用named区分;褐色是同时注册了两个不同的实现,用keyed区分)
public class AdminUserController : ControllerBase { public IUserService _userservice; private readonly IMapper _mapper; private readonly IComponentContext componentContext; public AdminUserController(IUserService userService,IMapper mapper,IComponentContext componentContext) { _userservice = userService; this._mapper = mapper; this.componentContext = componentContext; } [HttpGet("getuserByid")] public async Task控制器代码:AdminusercontrollerGetDtoAsync(int uid,int utype,int ukeyid) { switch (utype) { case 1: _userservice = componentContext.ResolveNamed ("one"); break; case 2: _userservice = componentContext.ResolveNamed ("two");break; default: break ; } switch (ukeyid) { case 1: _userservice = componentContext.ResolveKeyed (keyid.one); break; case 2: _userservice = componentContext.ResolveKeyed (keyid.two); break; } //var two = container.ResolveNamed ("two"); //builder.Build().ResolveNamed("two"); return await _userservice.GetUsers(uid); } }
黄色选中是固定注册,在构造函数中直接注入使用就可以。
蓝色和褐色选中的为 named和keyed,都需要使用到 autofac的IComponentContext 上下文对象,通过构造注入即可.
根据传来的不同参数确定使用哪个实例。
官方解释:https://autofaccn.readthedocs.io/zh/latest/advanced/keyed-services.html?highlight=named
我个人认为named更方便些可以使用 实现的类名当做named :
builder.RegisterType
(注:以上 AutofacModule中使用named注册的时候是一个一个注册的, 可以使用批量注册,以下是批量注册和使用,不清楚这种方式是不是更好一些。)
#region 批量注册
public class AutofacMoule : Module { protected override void Load(ContainerBuilder builder) { typeof(IUserService).Assembly.GetTypes() .Where(t => t.GetInterfaces().Contains(typeof(IUserService))).ToList() .ForEach(w => builder.RegisterType(w).Named批量注册(w.Name).As ().InstancePerDependency() ); } }
#endregion 批量注册结束
演示结果:userService 在名字前加了一个字符串“7788”
twoUserService取出数据没做操作
keyid=1 实例的是userService 输出名字“7788Duh”;
kid=2实例的是twouserService 输出名字“DuhDuh”;
( 注:name:duhduh 两遍是用automapper做的两个字段映射,不用在意。)
AutoFac生命周期 https://autofaccn.readthedocs.io/zh/latest/lifetime/instance-scope.html
每个依赖一个实例(Instance Per Dependency)
单一实例(Single Instance)
每个生命周期作用域一个实例(Instance Per Lifetime Scope)
每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)
每个请求一个实例(Instance Per Request)
每次被拥有一个实例(Instance Per Owned)
线程作用域(Thread Scope)