插件化架构指宿主程序运行时动态加载、调用外部独立编译的插件模块以扩展功能,无需重启或重新编译;在.NET中依赖AssemblyLoadContext等机制实现隔离与卸载,并需注意框架一致、接口解耦、路径规范等细节。
插件化架构是指主程序(宿主)在运行时动态加载、调用外部独立编译的模块(插件),实现功能扩展而无需重新编译或重启主程序。在 C# 和 .NET 中,这通常依赖于 AssemblyLoadContext(.NET Core 3.0+)、AppDomain(.NET Framework)或更现代的 Microsoft.Extensions.Hosting + IHostedService 组合来隔离和管理插件生命周期。
以 .NET 6/7/8 为例,不依赖第三方框架,纯 SDK 实现:
Plugin.Abstractions),声明插件必须
实现的接口,例如:public interface IPlugin { string Name { get; } void Execute(); }
MyFeaturePlugin),引用 Plugin.Abstractions,实现接口并标记为公开类(避免 internal)AssemblyLoadContext.LoadFromAssemblyPath() 加载插件 DLL;再用 assembly.GetTypes().FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract) 找到实现类;最后通过 Activator.CreateInstance() 创建实例并调用isCollectible: true,否则插件 DLL 会被锁住,重复加载失败让插件系统更健壮、易维护:
AssemblyMetadata("PluginType", "ReportGenerator"),宿主可通过 assembly.GetCustomAttribute() 过滤类型AssemblyLoadContext 中重写 Load 方法,按需从插件目录或共享 nuget 文件夹加载依赖Enabled == true 的项,便于灰度发布或环境差异化很多初学者卡在这几处:
net6.0;混用 netstandard2.0 插件在 .NET 6 宿主中可能因 API 不可用而运行时报错PreserveNewest
Path.GetFullPath() 标准化,避免加载失败