Autofac模块具有自己的依赖关系

Dav*_*bin 8 autofac

我正在努力解决如何在模块中组织我的Autofac组件注册,因为某些模块本身具有依赖性.

我在一个接口中实现了配置数据的抽象( web.config):

interface IConfigurationProvider
{
    T GetSection<T>(string sectionName)
        where T : System.Configuration.ConfigurationSection;
}
Run Code Online (Sandbox Code Playgroud)

以及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 */);
    }
}
Run Code Online (Sandbox Code Playgroud)

由于RegisterType()扩展方法不接受注册委托(Func<IComponentContext, T>),就像Register()这样,我无法注册IConfigurationProvider前面的内容,然后在我注册配置中指定的类型时解析它,例如:

// this would be nice...
builder.RegisterType(c => c.Resolve<IConfigurationProvider>().GetSection<CustomConfigSection>("sectionName").TypeFromConfig);
Run Code Online (Sandbox Code Playgroud)

这意味着我需要能够注册具有和不依赖的模块IConfigurationProvider.

很明显如何手动实例化每个模块并注册它:

IConfigurationProvider configProvider = ...;
var builder = new ContainerBuilder();
builder.RegisterModule(new DependentModule(configProvider));
builder.RegisterModule(new IndependentModule());
using (var container = builder.Build())
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

但我不想手动实例化我的模块 - 我想扫描模块的程序集并自动注册它们(如本问题所述).所以我必须使用反射来扫描程序集的IModule类型,并用于Activator.CreateInstance创建可注册的实例.但是我如何知道是否传递IConfigurationProvider一个构造函数参数.当其他模块具有其他或不同的依赖关系时会发生什么?

必须有一种更简单的方法来完成基本任务:注册通过接口提供的某些配置中指定的类型,对吗?那我该怎么做?

Jim*_*lla 7

你可以这样做:

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
    {
    }
}
Run Code Online (Sandbox Code Playgroud)