获取通过 Autofac 模块注册注册的对象的多个实例
Get multiple instances of an object registered via Autofac module registration
我有一个用例,我需要从 Autofac 模块中获取两个对象的副本并传递它们以注册不同的类型。
在下面的代码示例中,
- 我想通过配置
dbConfig
传递一个 DataProtectionService 对象来注册 MyDbRepo
。
- 同样,我想通过配置
cacheConfig
传递一个DataProtectionService对象来注册MyCacheRepo
。
但是,我不确定该怎么做?我在这里错过了一些非常基本的东西吗?
我没有删除此 DataProtectionServiceModule
的选项。有什么方法可以实现我的期望吗?
public class DataProtectionServiceModule : Module
{
private readonly string config;
public DataProtectionServiceModule(string config)
{
this.config = config;
}
protected override void Load(ContainerBuilder builder)
{
builder.Register<Token>(compContext =>
{ // a complex logic here
}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
}).As<IDataProtectionService>();
}
}
public class MyDbRepo : IMyDbRepo
{
IDataProtectionService dataProtectionService;
public MyDbRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public class MyCacheRepo : IMyCacheRepo
{
IDataProtectionService dataProtectionService;
public MyCacheRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
// Program.cs of my backend micro service
var builder = new ContainerBuilder();
builder.RegisterModule(new DataProtectionServiceModule("dbConfig"));
builder.RegisterModule(new DataProtectionServiceModule("cacheConfig")); // I have figured, this is wrong.
builder.RegisterType<MyDbRepo>().As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().As<IMyCacheRepo>().SingleInstance();
您可以使用 Keyed Services。然后在您的注册中添加特定的 Resolve
.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// Program.cs of my backend micro service
var builder = new ContainerBuilder();
builder.RegisterModule(new DataProtectionServiceModule("dbConfig", DeviceState.Db));
builder.RegisterModule(new DataProtectionServiceModule("cacheConfig", DeviceState.Cache)); // I have figured, this is wrong.
builder.RegisterType<MyDbRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Db)
)
).As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Cache)
)
).As<IMyCacheRepo>().SingleInstance();
var container = builder.Build();
var cache = container.Resolve<IMyCacheRepo>();
var db = container.Resolve<IMyDbRepo>();
}
}
public enum DeviceState { Cache, Db }
public class DataProtectionServiceModule : Module
{
private readonly string config;
private readonly DeviceState _state;
public DataProtectionServiceModule(string config, DeviceState state)
{
this.config = config;
_state = state;
}
protected override void Load(ContainerBuilder builder)
{
builder.Register<Token>(compContext =>
{ // a complex logic here
}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
return new DataProtectionService(config);
}).Keyed<IDataProtectionService>(_state);
}
}
public class DataProtectionService : IDataProtectionService
{
public string Config { get; }
public DataProtectionService(string config)
{
Config = config;
}
}
public class MyDbRepo : IMyDbRepo
{
IDataProtectionService dataProtectionService;
public MyDbRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public interface IDataProtectionService
{
}
public interface IMyDbRepo
{
}
public class MyCacheRepo : IMyCacheRepo
{
IDataProtectionService dataProtectionService;
public MyCacheRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public interface IMyCacheRepo
{
}
或者您可以使用 Named Services 和配置名称 dbConfig
和 cacheConfig
。这样您就不需要更改 DataProtectionServiceModule
.
的构造函数
builder.RegisterType<MyDbRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("dbConfig")
)
).As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("cacheConfig")
你的模块:
protected override void Load(ContainerBuilder builder)
{
//builder.Register<Token>(compContext =>
//{ // a complex logic here
//}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
return new DataProtectionService(config);
}).Named<IDataProtectionService>(config);
}
我有一个用例,我需要从 Autofac 模块中获取两个对象的副本并传递它们以注册不同的类型。
在下面的代码示例中,
- 我想通过配置
dbConfig
传递一个 DataProtectionService 对象来注册MyDbRepo
。 - 同样,我想通过配置
cacheConfig
传递一个DataProtectionService对象来注册MyCacheRepo
。
但是,我不确定该怎么做?我在这里错过了一些非常基本的东西吗?
我没有删除此 DataProtectionServiceModule
的选项。有什么方法可以实现我的期望吗?
public class DataProtectionServiceModule : Module
{
private readonly string config;
public DataProtectionServiceModule(string config)
{
this.config = config;
}
protected override void Load(ContainerBuilder builder)
{
builder.Register<Token>(compContext =>
{ // a complex logic here
}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
}).As<IDataProtectionService>();
}
}
public class MyDbRepo : IMyDbRepo
{
IDataProtectionService dataProtectionService;
public MyDbRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public class MyCacheRepo : IMyCacheRepo
{
IDataProtectionService dataProtectionService;
public MyCacheRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
// Program.cs of my backend micro service
var builder = new ContainerBuilder();
builder.RegisterModule(new DataProtectionServiceModule("dbConfig"));
builder.RegisterModule(new DataProtectionServiceModule("cacheConfig")); // I have figured, this is wrong.
builder.RegisterType<MyDbRepo>().As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().As<IMyCacheRepo>().SingleInstance();
您可以使用 Keyed Services。然后在您的注册中添加特定的 Resolve
.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// Program.cs of my backend micro service
var builder = new ContainerBuilder();
builder.RegisterModule(new DataProtectionServiceModule("dbConfig", DeviceState.Db));
builder.RegisterModule(new DataProtectionServiceModule("cacheConfig", DeviceState.Cache)); // I have figured, this is wrong.
builder.RegisterType<MyDbRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Db)
)
).As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Cache)
)
).As<IMyCacheRepo>().SingleInstance();
var container = builder.Build();
var cache = container.Resolve<IMyCacheRepo>();
var db = container.Resolve<IMyDbRepo>();
}
}
public enum DeviceState { Cache, Db }
public class DataProtectionServiceModule : Module
{
private readonly string config;
private readonly DeviceState _state;
public DataProtectionServiceModule(string config, DeviceState state)
{
this.config = config;
_state = state;
}
protected override void Load(ContainerBuilder builder)
{
builder.Register<Token>(compContext =>
{ // a complex logic here
}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
return new DataProtectionService(config);
}).Keyed<IDataProtectionService>(_state);
}
}
public class DataProtectionService : IDataProtectionService
{
public string Config { get; }
public DataProtectionService(string config)
{
Config = config;
}
}
public class MyDbRepo : IMyDbRepo
{
IDataProtectionService dataProtectionService;
public MyDbRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public interface IDataProtectionService
{
}
public interface IMyDbRepo
{
}
public class MyCacheRepo : IMyCacheRepo
{
IDataProtectionService dataProtectionService;
public MyCacheRepo(IDataProtectionService dataProtectionService)
{
this.dataProtectionService = dataProtectionService;
}
}
public interface IMyCacheRepo
{
}
或者您可以使用 Named Services 和配置名称 dbConfig
和 cacheConfig
。这样您就不需要更改 DataProtectionServiceModule
.
builder.RegisterType<MyDbRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("dbConfig")
)
).As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
(pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("cacheConfig")
你的模块:
protected override void Load(ContainerBuilder builder)
{
//builder.Register<Token>(compContext =>
//{ // a complex logic here
//}).OnRelease(instance => instance.Dispose());
builder.Register(c =>
{
// a logic to generate an object of IDataProtectionService
// this logic involves the use of config field of this class.
return new DataProtectionService(config);
}).Named<IDataProtectionService>(config);
}