I have an application that uses two different modules (implemented as Autofac.Module) that register the services they provide. Each simply has an adapter for hardware devices that produce the same data via different methods.
public class AdapterA : IDataProducer {
public AdapterA(IConfigSource conf){
// do something with conf, like setting an IP address, port etc.
}
}
public ModuleA : Module{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AdapterA>().As<IDataProducer>();
// the config source is specific to Module A, as it contains details about the hardware
builder.Register(c => new IniConfigSource("moduleA.ini")).As<IConfigSource>();
}
}
Now when I register that module in my main application, it works fine and the dependencies are resolved correctly.
builder.RegisterModule<ModuleA>();
In my main application, I also make use of an IConfigSource
, to read/write application specific settings. The problem becomes obvious when I register another IConfigSource
there, with a different settings file.
protected override void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule<ModuleA>();
builder.Register(c => new IniConfigSource("mainprogram.ini")).As<IConfigSource>();
}
At Resolution time, the second registration takes effect and my ModuleA
receives the wrong configuration file reader.
Looking around for a solution, I tried to work around this by changing the registration type, like so:
public interface IModuleAConfigSource : IConfigSource {}
and
builder.Register(c => new IniConfigSource("moduleA.ini")).As<IModuleAConfigSource>();
but that does not work. Autofac complains at resolution time that the type IniconfigSource
is not assignable to the interface IModuleAConfigSource.
I use constructor injection with registration in a single function at application startup.
What would be a good strategy here? I know I can use concrete types to solve this, but is there a way to keep a registration module-local, i.e. when resolving a type to use the registration from that module?