I have a use case where I need to get two copies of objects registered from Autofac module and pass them to register different types.
In the below code sample,
dbConfig
to register MyDbRepo
.cacheConfig
to register MyCacheRepo
.But, I am not sure how should I do that? Am I missing something really basic here?
I don't have an option to remove this DataProtectionServiceModule
. Is there a way to achieve what I am expecting?
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();
You can use Keyed Services. And then in your registration add a specific 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
{
}
Alternatively you can use Named Services and the config-name dbConfig
and cacheConfig
. This way you do not need to change the constructor of 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")
And your module:
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);
}