.NET Core Web API插件目录结构调整及加载异常问题咨询
实现插件独立目录结构的完整方案
1. 确保插件配置文件被复制到目标目录
在每个插件项目(比如Plugin1.csproj)中添加以下配置,让config.json随插件一起复制到指定子目录:
<ItemGroup> <None Update="config.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
配合你之前在主项目中设置的DestinationSubDirectory,构建后插件的dll和config.json会自动进入Plugins/Plugin1目录。
2. 修复程序集加载找不到的问题
默认的.NET程序集加载器只会搜索主程序目录,不会遍历Plugins子目录,因此需要自定义AssemblyLoadContext来加载指定目录的插件:
using System.Reflection; using System.Runtime.Loader; public class PluginLoadContext : AssemblyLoadContext { private readonly string _pluginDir; public PluginLoadContext(string pluginDir) : base(isCollectible: true) { _pluginDir = pluginDir; } protected override Assembly? Load(AssemblyName assemblyName) { var assemblyPath = Path.Combine(_pluginDir, $"{assemblyName.Name}.dll"); return File.Exists(assemblyPath) ? LoadFromAssemblyPath(assemblyPath) : null; } }
在主项目中加载插件时,使用这个上下文遍历并加载子目录中的插件:
var pluginsRoot = Path.Combine(AppContext.BaseDirectory, "Plugins"); foreach (var pluginDir in Directory.GetDirectories(pluginsRoot)) { var pluginDllPath = Path.Combine(pluginDir, $"{Path.GetFileName(pluginDir)}.dll"); if (!File.Exists(pluginDllPath)) continue; var loadContext = new PluginLoadContext(pluginDir); var pluginAssembly = loadContext.LoadFromAssemblyPath(pluginDllPath); // 这里可以根据插件接口类型初始化插件,例如: // var plugin = pluginAssembly.CreateInstance("Plugin1.Plugin1") as IPlugin; // plugin?.Initialize(); }
3. 插件自身读取独立配置文件
插件不能直接使用主项目的IConfiguration(默认指向主目录),需要通过自身程序集路径定位配置文件:
using Microsoft.Extensions.Configuration; using System.Reflection; public class Plugin1 : IPlugin { public void Initialize() { var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var configPath = Path.Combine(assemblyDir, "config.json"); var config = new ConfigurationBuilder() .AddJsonFile(configPath, optional: false, reloadOnChange: true) .Build(); // 使用配置内容,例如读取某个配置项: // var settingValue = config["PluginSetting"]; } }
4. 优化主项目的插件引用配置
在主项目的ProjectReference中添加<Private>False</Private>,避免插件被额外复制到主程序根目录:
<ProjectReference Include="..\Plugins\Plugin1\Plugin1.csproj"> <DestinationSubDirectory>Plugins\Plugin1\</DestinationSubDirectory> <Private>False</Private> </ProjectReference>
不需要退回到将所有文件放在主目录的方案,按照上述步骤即可实现你想要的结构化插件布局,每个插件拥有独立的配置文件和目录。
内容的提问来源于stack exchange,提问作者qlabfgerkaSmurf
相关产品推荐
相关产品推荐

