using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; namespace MAX.Plugins; /// 插件独立配置,不合并宿主或其他插件配置。 public sealed class PluginContext : IDisposable { private int disposed; public string Id { get; } public string DirectoryPath { get; } public IHostEnvironment Environment { get; } public IConfigurationRoot Configuration { get; } public PluginContext(string id, string directoryPath, IHostEnvironment environment) { ArgumentException.ThrowIfNullOrWhiteSpace(id); ArgumentNullException.ThrowIfNull(environment); Id = id; DirectoryPath = Path.GetFullPath(directoryPath); Environment = environment; Configuration = new ConfigurationBuilder() .SetBasePath(DirectoryPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) .AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: true, reloadOnChange: false) .AddEnvironmentVariables($"Plugins__{id}__") .Build(); } public string RequireConfiguration(string key) => !string.IsNullOrWhiteSpace(Configuration[key]) ? Configuration[key]! : throw new InvalidOperationException($"插件 {Id} 缺少配置 {key},请检查 {Path.Combine(DirectoryPath, "appsettings.json")}。"); public void Dispose() { if (Interlocked.Exchange(ref disposed, 1) == 0) (Configuration as IDisposable)?.Dispose(); } } /// 按插件类型注入的上下文视图,配置及其生命周期由宿主的 PluginContext 统一管理。 public sealed class PluginContext(PluginContext context) where TPlugin : IPlugin { /// 插件唯一标识。 public string Id => context.Id; /// 插件程序集和配置所在目录。 public string DirectoryPath => context.DirectoryPath; /// 当前宿主环境。 public IHostEnvironment Environment => context.Environment; /// 与插件入口共享的独立配置实例。 public IConfigurationRoot Configuration => context.Configuration; /// 读取必填配置,缺失时沿用插件上下文的错误说明。 public string RequireConfiguration(string key) => context.RequireConfiguration(key); }