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.RegisterType<twoUserService>().As<IUserService>().SingleInstance();
builder.RegisterType<twoUserService>().Named<IUserService>("two").As<IUserService>().InstancePerDependency();
builder.RegisterType<UserService>().Named<IUserService>("one").As<IUserService>().InstancePerDependency();
builder.RegisterType<UserService>().Keyed<IUserService>(keyid.one).As<IUserService>().InstancePerDependency();
builder.RegisterType<twoUserService>().Keyed<IUserService>(keyid.two).As<IUserService>().InstancePerDependency();
}
}
public enum keyid
{
one = 1,
two = 2
}
}
AutofacModule
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.RegisterType<twoUserService>().As<IUserService>().SingleInstance();
builder.RegisterType<twoUserService>().Named<IUserService>("two").As<IUserService>().InstancePerDependency();
builder.RegisterType<UserService>().Named<IUserService>("one").As<IUserService>().InstancePerDependency();
builder.RegisterType<UserService>().Keyed<IUserService>(keyid.one).As<IUserService>().InstancePerDependency();
builder.RegisterType<twoUserService>().Keyed<IUserService>(keyid.two).As<IUserService>().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<UsersDto> GetDtoAsync(int uid,int utype,int ukeyid)
{
switch (utype)
{
case 1: _userservice = componentContext.ResolveNamed<IUserService>("one"); break;
case 2: _userservice = componentContext.ResolveNamed<IUserService>("two");break;
default: break ;
}
switch (ukeyid)
{
case 1: _userservice = componentContext.ResolveKeyed<IUserService>(keyid.one); break;
case 2: _userservice = componentContext.ResolveKeyed<IUserService>(keyid.two); break;
}
//var two = container.ResolveNamed<IUserService>("two");
//builder.Build().ResolveNamed<IUserService>("two");
return await _userservice.GetUsers(uid);
}
}
控制器代码:Adminusercontroller
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<UsersDto> GetDtoAsync(int uid,int utype,int ukeyid)
{
switch (utype)
{
case 1: _userservice = componentContext.ResolveNamed<IUserService>("one"); break;
case 2: _userservice = componentContext.ResolveNamed<IUserService>("two");break;
default: break ;
}
switch (ukeyid)
{
case 1: _userservice = componentContext.ResolveKeyed<IUserService>(keyid.one); break;
case 2: _userservice = componentContext.ResolveKeyed<IUserService>(keyid.two); break;
}
//var two = container.ResolveNamed<IUserService>("two");
//builder.Build().ResolveNamed<IUserService>("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<twoUserService>().Named<IUserService>(nameof(twoUserService)).As<IUserService>().InstancePerDependency();
(注:以上 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<IUserService>(w.Name).As<IUserService>().InstancePerDependency()
);
}
}
批量注册
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<IUserService>(w.Name).As<IUserService>().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)

浙公网安备 33010602011771号