namespace XFEExtension.NetCore.AutoConfig; /// /// 为同一种配置类型创建相互独立的实例和文件存储。适用于多租户、多账号或多工作区场景。 /// /// 配置类型 public sealed class ProfileStore where TProfile : XFEProfile, new() { private readonly object syncRoot = new(); private readonly Func profileFactory; private readonly string profilePath; private TProfile current; /// /// 创建配置存储。 /// /// 包含扩展名的完整配置文件路径 /// 是否在创建时读取文件 /// 可选实例工厂;省略时调用公共无参构造函数 public ProfileStore(string profilePath, bool autoLoad = true, Func? profileFactory = null) { ArgumentException.ThrowIfNullOrWhiteSpace(profilePath); this.profilePath = Path.GetFullPath(profilePath); this.profileFactory = profileFactory ?? (static () => new TProfile()); current = CreateProfile(); if (autoLoad) current = (TProfile)current.InstanceLoadProfile(CreateProfile); } /// 实际使用的完整配置文件路径。 public string ProfilePath => profilePath; /// 当前实例。加载或导入只有在迁移和验证成功后才会替换它。 public TProfile Current { get { lock (syncRoot) return current; } } /// 重新从文件加载配置。 public void Load() { lock (syncRoot) current = (TProfile)current.InstanceLoadProfile(CreateProfile); } /// 立即保存当前配置。 public void Save() { lock (syncRoot) current.InstanceSaveProfile(); } /// 异步保存当前配置。 public Task SaveAsync(CancellationToken cancellationToken = default) { TProfile snapshot; lock (syncRoot) snapshot = current; return snapshot.InstanceSaveProfileAsync(cancellationToken); } /// 等待调用前已经请求的自动保存完成。 public Task FlushAsync(CancellationToken cancellationToken = default) { TProfile snapshot; lock (syncRoot) snapshot = current; return snapshot.InstanceFlushProfileAsync(cancellationToken); } /// 删除此存储对应的配置文件。 public void Delete() { lock (syncRoot) current.InstanceDeleteProfile(); } /// 导出包含版本元数据的配置文本。 public string Export() { lock (syncRoot) return current.InstanceExportProfile(); } /// 以原始字节导出包含版本元数据的配置;MessagePack 模式不会产生 Base64 中间文本。 public byte[] ExportBytes() { lock (syncRoot) return current.InstanceExportProfileBytes(); } /// 导入配置文本;迁移或验证失败时保持当前实例不变。 public void Import(string profileContent) { ArgumentNullException.ThrowIfNull(profileContent); lock (syncRoot) current = (TProfile)current.InstanceImportProfile(profileContent, CreateProfile); } /// 从原始字节导入配置;迁移或验证失败时保持当前实例不变。 public void ImportBytes(ReadOnlyMemory profileContent) { lock (syncRoot) current = (TProfile)current.InstanceImportProfileBytes(profileContent, CreateProfile); } /// /// 在实例锁内修改配置,并在修改成功后请求一次合并自动保存。 /// public void Update(Action update) { ArgumentNullException.ThrowIfNull(update); lock (syncRoot) lock (current.ProfileSyncRoot) { update(current); current.InstanceRequestSaveProfile(); } } /// 在实例锁内读取配置。 public TResult Read(Func read) { ArgumentNullException.ThrowIfNull(read); lock (syncRoot) lock (current.ProfileSyncRoot) return read(current); } private TProfile CreateProfile() { var profile = profileFactory() ?? throw new InvalidOperationException("配置实例工厂返回了 null"); profile.Initialize(); profile.CurrentProfilePath = profilePath; return profile; } }