You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Simple Injector中结合配置动态注册带构造参数的插件?

基于Simple Injector的插件动态加载最佳实践调整方案

核心思路

将插件加载、配置读取、依赖注入逻辑全部迁移至组合根(通常是应用启动入口,如Program.cs或Startup类),ViewModel仅依赖抽象接口,不再负责插件加载相关逻辑。

具体实现步骤

1. 定义结构化插件配置模型

把App.Config中的插件配置抽象为强类型模型,避免硬编码读取:

public class PluginConfig
{
    public string Name { get; set; }
    public string Language { get; set; }
    // 按需添加其他插件所需配置项
}

2. 在组合根统一读取插件配置

通过ConfigurationManager集中读取App.Config中的插件配置:

private static IEnumerable<PluginConfig> LoadPluginConfigs()
{
    var configSection = ConfigurationManager.GetSection("PluginSettings") as NameValueCollection;
    if (configSection == null) yield break;

    yield return new PluginConfig
    {
        Name = configSection["Name"],
        Language = configSection["Language"]
        // 读取其他配置项
    };
    // 多插件场景可循环读取不同配置节点
}

3. 动态加载插件并完成依赖注册

在组合根中完成程序集加载、插件类型扫描,同时注入配置参数到插件构造函数:

public static void ConfigureContainer(Container container)
{
    // 1. 读取插件配置
    var pluginConfigs = LoadPluginConfigs().ToList();

    // 2. 加载Plugins目录下的所有插件程序集
    var pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
    var pluginAssemblies = Directory.GetFiles(pluginDir, "*.dll")
        .Select(Assembly.LoadFrom)
        .ToList();

    // 3. 扫描并注册所有IPlugin实现类,注入对应配置
    foreach (var assembly in pluginAssemblies)
    {
        var pluginTypes = assembly.GetTypes()
            .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract);

        foreach (var pluginType in pluginTypes)
        {
            // 多插件场景可通过名称匹配对应配置
            var config = pluginConfigs.FirstOrDefault();
            if (config == null) continue;

            // 通过Lambda表达式注入构造函数参数
            container.Register(typeof(IPlugin), 
                () => Activator.CreateInstance(pluginType, config.Name, config.Language), 
                Lifestyle.Transient);
        }
    }

    // 4. 注册ViewModel,依赖IPlugin抽象
    container.Register<MainViewModel>();
}

4. 改造ViewModel,仅依赖抽象接口

ViewModel不再依赖工厂,直接通过构造函数注入插件实例或集合:

public class MainViewModel
{
    private readonly IEnumerable<IPlugin> _plugins;

    public MainViewModel(IEnumerable<IPlugin> plugins)
    {
        _plugins = plugins;
    }

    // 业务逻辑中直接使用插件
    public void ExecutePlugins()
    {
        foreach (var plugin in _plugins)
        {
            plugin.Run();
        }
    }
}

5. 移除独立PluginFactory

原PluginFactory的职责已合并到组合根的注册流程中,无需保留独立工厂类,所有对象实例化由Simple Injector容器统一管理。

关键优化点

  • 单一职责:组合根集中处理依赖注册、插件加载,ViewModel专注业务逻辑
  • 依赖倒置:ViewModel依赖IPlugin抽象,与具体插件实现解耦
  • 集中配置:所有配置读取逻辑统一在组合根,避免分散在业务代码中
  • 符合容器最佳实践:所有对象创建由容器管控,杜绝手动实例化导致的依赖混乱

内容的提问来源于stack exchange,提问作者James0n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:25:14