C#中如何高效从外部程序集扩展ProcessingManager功能?
优化外部程序集扩展ProcessingManager的方案
替代全程序集遍历的可行方案
1. 用MEF框架实现自动发现
MEF是.NET内置的可扩展性框架,专门解决插件式扩展场景,完全匹配你的需求:
- 在外部程序集的
IProcessor实现类上标记[Export(typeof(IProcessor))] - 在
ProcessingManager中通过CompositionContainer批量导入所有实现,不用遍历所有程序集 - 示例代码:
// 外部程序集的处理器实现 [Export(typeof(IProcessor))] public class DemoProcessor : IProcessor { public void Process(TypeDefinition typeDef) { // 自定义处理逻辑 } } // ProcessingManager中的加载逻辑 var pluginCatalog = new DirectoryCatalog("你的插件存放目录"); var container = new CompositionContainer(pluginCatalog); var allProcessors = container.GetExportedValues<IProcessor>(); foreach (var processor in allProcessors) { processor.Process(targetTypeDef); } - 优点:自动识别指定接口的实现,支持按需加载,性能比全程序集遍历高很多
2. 配置文件指定扩展程序集
在主程序的配置文件(如appsettings.json)里列出所有包含IProcessor实现的程序集名称,只加载这些指定的程序集:
- 配置示例:
{ "ProcessorAssemblies": [ "OrderProcessor.dll", "UserProcessor.dll" ] } - 加载逻辑:
var assemblyNames = Configuration.GetSection("ProcessorAssemblies").Get<string[]>(); foreach (var assemblyName in assemblyNames) { var assemblyPath = Path.Combine("插件目录", assemblyName); var assembly = Assembly.LoadFrom(assemblyPath); var processorTypes = assembly.GetTypes() .Where(t => typeof(IProcessor).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var type in processorTypes) { var processor = (IProcessor)Activator.CreateInstance(type); // 将处理器加入ProcessingManager管理 } } - 优点:完全可控,性能最优,适合明确知道扩展程序集的场景
3. 用AssemblyLoadContext按需加载
结合AssemblyLoadContext加载指定目录下的程序集,同时跳过无效程序集,减少不必要的加载:
- 核心代码:
var processorLoadContext = new AssemblyLoadContext("ProcessorContext", isCollectible: true); var pluginDir = new DirectoryInfo("插件目录"); foreach (var dllFile in pluginDir.GetFiles("*.dll")) { try { var assembly = processorLoadContext.LoadFromAssemblyPath(dllFile.FullName); var processorTypes = assembly.GetTypes() .Where(t => typeof(IProcessor).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); if (processorTypes.Any()) { // 实例化并管理这些处理器 } } catch (BadImageFormatException) { // 跳过非.NET程序集 continue; } } - 优点:隔离扩展程序集的加载上下文,避免影响主程序,同时只处理可能包含目标实现的程序集
方案对比
以上三种方案都避免了遍历系统所有程序集的低效操作,要么依赖框架自动发现,要么通过配置明确范围,要么按需筛选加载,在性能和可控性上都远优于原有的全遍历方式。
内容的提问来源于stack exchange,提问作者FeXseven
相关产品推荐
相关产品推荐

