如何在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
相关产品推荐
相关产品推荐

