跳过 autofac.json 中配置的未知 autofac 模块

Skip unknown autofac modules configured in autofac.json

我的应用程序是从 autofac.json 文件初始化的:

{
    "defaultAssembly": "Application",
        "modules": [
            { "type": "Application.Plugin1.Module, Application.Plugin1" },
            { "type": "Application.Plugin2.Module, Application.Plugin2" },
            { "type": "Application.Plugin3.Module, Application.Plugin3" }
        ]
}

但每个插件都不是强制性的。

当我 运行 缺少插件的应用程序时,抛出以下异常:

Unhandled Exception: System.InvalidOperationException: The type 'Application.Plugin2.Module, Application.Plugin2' could not be found. It may require assembly qualification, e.g. "MyType, MyAssembly".
   at Autofac.Configuration.Core.ConfigurationExtensions.GetType(IConfiguration configuration, String key, Assembly defaultAssembly)
   at Autofac.Configuration.Core.ModuleRegistrar.RegisterConfiguredModules(ContainerBuilder builder, IConfiguration configuration)
   at Autofac.Configuration.Core.ConfigurationRegistrar.RegisterConfiguration(ContainerBuilder builder, IConfiguration configuration)
   at Autofac.Module.Configure(IComponentRegistry componentRegistry)
   at Autofac.ContainerBuilder.Build(IComponentRegistry componentRegistry, Boolean excludeDefaultModules)
   at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)

如何忽略应用程序文件夹中不存在的插件?

这是 Autofac.Configuration.ConfigurationModule 的默认行为。

您可以通过实现自定义 IModuleRegistrar

来更改配置模块的加载方式

我们可以轻松修改默认的 ModuleRegistrar 实现来添加可选模块。

// based on https://github.com/autofac/Autofac.Configuration/blob/0f84f3569eb5a59013859f6eaa9b1ea4cf8e77a1/src/Autofac.Configuration/Core/ModuleRegistrar.cs
public class OptionalModuleRegistrar : IModuleRegistrar
{
    public virtual void RegisterConfiguredModules(ContainerBuilder builder, IConfiguration configuration)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        if (configuration == null)
        {
            throw new ArgumentNullException(nameof(configuration));
        }

        var defaultAssembly = configuration.DefaultAssembly();
        foreach (var moduleElement in configuration.GetSection("modules").GetChildren())
        {
            var moduleTypeName = moduleElement["type"];
            var moduleType = GetType(moduleTypeName, defaultAssembly);
            if (moduleType == null)
            {
                // Log moduleTypeName
                Console.WriteLine($"{moduleTypeName} module not found");
                continue;
            }

            var module = (IModule)null;
            using (var moduleActivator = new ReflectionActivator(
                moduleType,
                new DefaultConstructorFinder(),
                new MostParametersConstructorSelector(),
                moduleElement.GetParameters("parameters"),
                moduleElement.GetProperties("properties")))
            {
                module = (IModule)moduleActivator.ActivateInstance(new ContainerBuilder().Build(), Enumerable.Empty<Parameter>());
            }

            builder.RegisterModule(module);
        }
    }

    private Type GetType(String moduleTypeName, Assembly defaultAssembly)
    {
        var moduleType = Type.GetType(moduleTypeName);
        if (moduleType == null && defaultAssembly != null)
        {
            moduleType = defaultAssembly.GetType(moduleTypeName, false, true);
        }

        return moduleType;
    }
}

你可以像这样使用它:

// Add the configuration to the ConfigurationBuilder.
var config = new ConfigurationBuilder();
config.AddJsonFile("autofac.json");

// Register the ConfigurationModule with Autofac.
var module = new ConfigurationModule(config.Build());
module.ConfigurationRegistrar = new ConfigurationRegistrar(
    new ComponentRegistrar(), 
    new OptionalModuleRegistrar());
var builder = new ContainerBuilder();
builder.RegisterModule(module);

// build the Autofac container
var container = builder.Build();