我正在努力解决如何在模块中组织我的Autofac组件注册,因为某些模块本身具有依赖性.
我在一个接口中实现了配置数据的抽象(即web.config):
interface IConfigurationProvider { T GetSection<T>(string sectionName) where T : System.Configuration.ConfigurationSection; }
以及ASP.NET(WebConfigurationProvider)和“桌面”应用程序(ExeConfigurationProvider)的实现.
然后我的一些autofac模块需要IConfigurationProvider作为构造函数参数,但有些则不需要:
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 */); } }
由于RegisterType()扩展方法不接受注册委托(Func< IComponentContext,T>),就像Register()那样,我无法预先注册IConfigurationProvider,然后在我注册类型时解析它在配置中指定,如:
// this would be nice... builder.RegisterType(c => c.Resolve<IConfigurationProvider>().GetSection<CustomConfigSection>("sectionName").TypeFromConfig);
这意味着我需要能够注册模块,无论是否依赖IConfigurationProvider.
很明显如何手动实例化每个模块并注册它:
IConfigurationProvider configProvider = ...; var builder = new ContainerBuilder(); builder.RegisterModule(new DependentModule(configProvider)); builder.RegisterModule(new IndependentModule()); using (var container = builder.Build()) { ... }
但我不想手动实例化我的模块 – 我想扫描模块的程序集并自动注册它们(如in this question所述).所以我必须使用反射来扫描程序集的IModule类型,并使用Activator.CreateInstance来创建可注册的实例.但是,我如何知道是否将IConfigurationProvider作为构造函数参数传递.当其他模块具有其他或不同的依赖关系时会发生什么?
你可以这样做:
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 { } }