I have an application which might needs to connect to multiple databases. But each module will only connect to one db. So I though it might make sense to isolate the db into each module so each module will get its own db auto resolved and I don’t need to bother with named registration. But to my astonishment, it seems that Autofac’s module is more a code module than a logical module (am I wrong here?): IA
[Test]
public void test_module_can_act_as_scope_container()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new Module1());
IContainer c = builder.Build();
var o = c.ResolveNamed<CB>("One");
Assert.That(o.A.Name, Is.EqualTo("One"));
builder = new ContainerBuilder();
builder.RegisterModule(new Module1());
builder.RegisterModule(new Module2());
c = builder.Build();
var t = c.ResolveNamed<CB>("One");
Assert.That(t.A.Name, Is.EqualTo("Two"));
}
And the interfaces/Modules used:
public interface IA
{
string Name { get; set; }
}
public class CA : IA
{
public string Name { get; set; }
}
public class CB
{
public CB(IA a)
{
A = a;
}
public IA A { get; private set; }
}
public class Module1 : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(c => new CA() { Name = "One" }).As<IA>();
builder.RegisterType<CB>().Named("One", typeof(CB));
}
}
public class Module2 : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(c => new CA() { Name = "Two" }).As<IA>();
builder.RegisterType<CB>().Named("Two", typeof(CB));
}
}
Yes, you’re kind of correct.
Modules serve only for splitting configuration into somewhat independent parts. They do not scope configuration in any way. Having modules is actually the same as if you merged all modules’
Loadmethods’ code into a single configuration method and then built the container.In your case your
Module2actually overrides the registration forIAinterface fromModule1.I’ve also been interested in finding a solution to the problem. I’ve come to the following approach:
Keyed service
Pros:
You can control which
IAinstances will be injected in each module.Contras:
IAcomponent ‘internal’ to the module – other modules can still resolve it using simpleResolve<IA>. Modules aren’t isolated.Hope this helps
UPDATE
In some cases it may be easier, and frankly more correct from design point of view, to make it this way:
Delegate registration
Pros:
CAto other modulesContras:
CAandCBhave complex dependencies and a lot of constructor parameters, you’ll end up with mess of constructing codeCAin several places inside a module, you’ll have to find a way to avoid copy-pastingNested Container instances
And yet another option is having an independent
Containerinside each module. This way all modules will be able to have their private container configurations. However, AFAIK, Autofac doesn’t provide any built-in means to somehow link severalContainerinstances. Although I suppose implementing this should not be very difficult.