I'm struggling with how to organize my Autofac component registrations in modules given that some of the modules themselves have dependencies.
I've implemented an abstraction of configuration data (i.e. web.config) in an interface:
interface IConfigurationProvider
{
T GetSection<T>(string sectionName)
where T : System.Configuration.ConfigurationSection;
}
along with implementations for ASP.NET (WebConfigurationProvider
) and "desktop" applications (ExeConfigurationProvider
).
Some of my autofac modules then require an IConfigurationProvider
as a constructor parameter, but some don't:
class DependentModule : Module
{
public DependentModule(IConfigurationProvider config)
{
_config = config;
}
protected override void Load(ContainerBuilder builder)
{
var configSection = _config.GetSection<CustomConfigSection>("customSection");
builder.RegisterType(configSection.TypeFromConfig);
}
private readonly IConfigurationProvider _config;
}
class IndependentModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(/* other stuff not based on configuration */);
}
}
Since the RegisterType()
extension method doesn't accept a registration delegate (Func<IComponentContext, T>
), like Register()
does, I can't register the IConfigurationProvider
up-front and then resolve it when I go to register the type specified in the configuration, something like:
// this would be nice...
builder.RegisterType(c => c.Resolve<IConfigurationProvider>().GetSection<CustomConfigSection>("sectionName").TypeFromConfig);
This means that I need to be able to register modules with and without a dependency on IConfigurationProvider
.
It's obvious how to manually instantiate each module and register it:
IConfigurationProvider configProvider = ...;
var builder = new ContainerBuilder();
builder.RegisterModule(new DependentModule(configProvider));
builder.RegisterModule(new IndependentModule());
using (var container = builder.Build())
{
...
}
But I don't want to manually instantiate my modules - I want to scan assemblies for modules and register them automatically (as discussed in this question). So I have to use reflection to scan the assembly for IModule
types, and use Activator.CreateInstance
to make registerable instances. But how do I know whether or not to pass an IConfigurationProvider
as a constructor parameter. And what happens when other modules have additional or different dependencies?
There's got to be a more straightforward way of accomplishing the basic task: register a type specified in some configuration provided via an interface, right? So how do I do that?