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);
}