Autofac Modules with their Dependencies

I struggle with how to organize the registration of Autofac components in modules, given that some of the modules themselves have dependencies.

I 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; } 

together with implementations for ASP.NET ( WebConfigurationProvider ) and "desktop" ( ExeConfigurationProvider ) ExeConfigurationProvider .

Some of my autofac modules then require IConfigurationProvider as a constructor parameter, but some of them do not:

 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 extension method RegisterType() does not accept the registration delegate ( Func<IComponentContext, T> ), for example Register() , I cannot register the front of IConfigurationProvider and then allow 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 dependency on IConfigurationProvider .

Obviously, how to manually create an instance of 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 create instances of my modules - I want to check 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 create registers. But how do I know whether to pass the IConfigurationProvider parameter as a constructor parameter. And what happens when other modules have additional or different dependencies?

There should be an easier way to accomplish the main task: register the type specified in some configuration provided through the interface, right? So how do I do this?

+6
source share
2 answers

You can do something like this:

 using System.Collections.Generic; using System.Linq; using Autofac; using Autofac.Core; using NUnit.Framework; namespace Yo_dawg { [TestFixture] public class I_heard_you_like_containers { [Test] public void So_we_built_a_container_to_build_your_container() { var modules = GetModules(); Assert.That(modules.Length, Is.EqualTo(4)); var builder = new ContainerBuilder(); foreach (var module in modules) builder.RegisterModule(module); var container = builder.Build(); } private IModule[] GetModules() { var builder = new ContainerBuilder(); var configurationProvider = new ConfigurationProvider(); builder.RegisterInstance(configurationProvider).AsImplementedInterfaces().ExternallyOwned(); builder.RegisterAssemblyTypes(GetType().Assembly) .Where(t => t.IsAssignableTo<IModule>()) .AsImplementedInterfaces(); using (var container = builder.Build()) return container.Resolve<IEnumerable<IModule>>().ToArray(); } } public class ModuleA : Module { public ModuleA(IConfigurationProvider config) { } } public class ModuleB : Module { public ModuleB(IConfigurationProvider config) { } } public class ModuleC : Module { } public class ModuleD : Module { } public interface IConfigurationProvider { } public class ConfigurationProvider : IConfigurationProvider { } } 
+6
source

For this scenario, Autofac's native XML configuration seems to cover the scripts that you are targeting. Adding a new IConfigurationProvider mechanism IConfigurationProvider like reusing this function already provided by the container. The basics are documented at: https://code.google.com/p/autofac/wiki/XmlConfiguration . The configuration syntax has built-in module support.

A good alternative to Paul Stovell, which allows you to register modules in code, but gets parameters from config - see http://www.paulstovell.com/convention-configuration . Hope this helps!

+2
source

Source: https://habr.com/ru/post/918395/


All Articles