【问题标题】:Autofac modules with their own dependencies具有自己依赖项的 Autofac 模块
【发布时间】:2012-06-18 19:12:37
【问题描述】:

鉴于某些模块本身具有依赖关系,我正在努力解决如何在模块中组织我的 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&lt;IComponentContext, T&gt;),就像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 作为构造函数参数传递。当其他模块有额外的或不同的依赖时会发生什么?

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

【问题讨论】:

  • 你最后解决了吗?我有非常相似的情况,但是我的依赖又具有另一个依赖(我想从 db 获取配置,所以我有一个依赖于 IRepoConfig 的 IConfigProvider)
  • @Learner,我最初使用 Autofac 和 MEF 的组合实现了一些东西,它模仿了 Jim Bolla 在下面的回答,但它非常复杂,我很快就把它删除了。我不再有依赖模块:由于我的主要用例是基于Type 的选择,因此我采取了注册 所有候选人的方法,然后根据来自ConfigurationSection 的属性解析。如果您愿意,我可以向您发送示例代码。
  • 好的,谢谢。我认为我不能在我的情况下使用 ConfigurationSection / xml。
  • 这可能会有所帮助:stackoverflow.com/a/57257634/1453867

标签: c# autofac


【解决方案1】:

你可以这样做:

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
    {
    }
}

【讨论】:

  • 感谢您的建议。我采用了类似的策略,但不喜欢它的某些方面。我将不得不重新审视这种方法。
【解决方案2】:

对于这个场景,Autofac 自己的 XML 配置似乎涵盖了您所针对的场景。添加一个新的IConfigurationProvider 机制似乎是对容器已经提供的这个功能的重新发明。基础知识记录在:https://code.google.com/p/autofac/wiki/XmlConfiguration。配置语法具有对模块的内置支持。

Paul Stovell 提供了一个不错的替代方案,它允许在代码中注册模块但从配置中接收参数 - 请参阅:http://www.paulstovell.com/convention-configuration。希望这会有所帮助!

【讨论】:

  • 感谢您的回复,但我不明白在这种情况下用 XML 表达我的 Autofac 配置如何帮助我。也许是因为我稍微弄乱了我的问题中的代码,并且我刚刚对其进行了编辑以更好地表达我正在尝试使用自定义 SectionHandler 类型的想法。
猜你喜欢
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 2018-03-18
  • 1970-01-01
  • 2017-08-21
  • 1970-01-01
相关资源
最近更新 更多