feat(cordis): 完成阶段5配置与调试工具
This commit is contained in:
@@ -27,9 +27,19 @@ namespace ShrinkContext.AppAdapter
|
||||
public string ModuleId = string.Empty;
|
||||
}
|
||||
|
||||
private sealed class CompositionOptions
|
||||
{
|
||||
public bool Enabled;
|
||||
public IReadOnlyDictionary<string, string>? Isolate;
|
||||
public IReadOnlyDictionary<string, IReadOnlyDictionary<string, object?>>? Intercept;
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, ModuleRecord> _modules = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly HashSet<string> _disabled = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly HashSet<string> _settingsDisabled = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ShrinkComponentCatalog _catalog;
|
||||
private Dictionary<string, CompositionOptions>? _compositionOptions;
|
||||
private bool _includeUnlistedEntries = true;
|
||||
private bool _started;
|
||||
|
||||
public ShrinkAppLoaderHost(ShrinkAppSettings? settings = null,
|
||||
@@ -60,7 +70,10 @@ namespace ShrinkContext.AppAdapter
|
||||
foreach (var rawId in Settings.disabledModuleIds ?? Array.Empty<string>())
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(rawId))
|
||||
{
|
||||
_settingsDisabled.Add(rawId.Trim());
|
||||
_disabled.Add(rawId.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +82,7 @@ namespace ShrinkContext.AppAdapter
|
||||
public ShrinkContextRuntime Context { get; }
|
||||
public ShrinkContextLoader Loader { get; }
|
||||
public bool IsRunning { get; private set; }
|
||||
public ShrinkAppCompositionDocument? AppliedComposition { get; private set; }
|
||||
|
||||
/// <summary>全部已注册模块 id(有序)。</summary>
|
||||
public IReadOnlyList<string> ModuleIds =>
|
||||
@@ -88,7 +102,10 @@ namespace ShrinkContext.AppAdapter
|
||||
TryGetLoaderFiber(moduleId, out var fiber) && fiber.State == ShrinkFiberState.Inactive;
|
||||
|
||||
public bool IsModuleDisabled(string moduleId) =>
|
||||
!string.IsNullOrWhiteSpace(moduleId) && _disabled.Contains(moduleId.Trim());
|
||||
!string.IsNullOrWhiteSpace(moduleId) &&
|
||||
(_disabled.Contains(moduleId.Trim()) ||
|
||||
(!_includeUnlistedEntries && _compositionOptions != null &&
|
||||
!_compositionOptions.ContainsKey(moduleId.Trim())));
|
||||
|
||||
/// <summary>查询模块当前纤程(被禁用模块返回 false)。</summary>
|
||||
public bool TryGetModuleFiber(string moduleId, out ShrinkFiber fiber) =>
|
||||
@@ -142,6 +159,46 @@ namespace ShrinkContext.AppAdapter
|
||||
_catalog.Register(normalizedId, componentFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在启动前应用声明式条目策略。组件工厂必须已经由组合根注册;配置不能实例化任意类型。
|
||||
/// ShrinkAppSettings.disabledModuleIds 仍作为额外禁用集合保留。
|
||||
/// </summary>
|
||||
public void ApplyComposition(ShrinkAppCompositionDocument document)
|
||||
{
|
||||
if (_started)
|
||||
throw new InvalidOperationException("Composition can only be applied before StartAsync.");
|
||||
|
||||
var copy = (document ?? throw new ArgumentNullException(nameof(document))).Clone();
|
||||
var options = new Dictionary<string, CompositionOptions>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var entry in copy.entries)
|
||||
{
|
||||
var id = entry.NormalizedId;
|
||||
if (!_modules.ContainsKey(id))
|
||||
throw new ShrinkLoaderException(
|
||||
$"Composition entry '{id}' has no registered module/component factory.");
|
||||
|
||||
options.Add(id, new CompositionOptions
|
||||
{
|
||||
Enabled = entry.enabled,
|
||||
Isolate = entry.BuildIsolate(),
|
||||
Intercept = entry.BuildIntercept()
|
||||
});
|
||||
}
|
||||
|
||||
_compositionOptions = options;
|
||||
_includeUnlistedEntries = copy.includeUnlistedEntries;
|
||||
AppliedComposition = copy;
|
||||
|
||||
_disabled.Clear();
|
||||
foreach (var id in _settingsDisabled)
|
||||
_disabled.Add(id);
|
||||
foreach (var pair in options)
|
||||
{
|
||||
if (!pair.Value.Enabled)
|
||||
_disabled.Add(pair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask StartAsync()
|
||||
{
|
||||
if (_started)
|
||||
@@ -172,10 +229,18 @@ namespace ShrinkContext.AppAdapter
|
||||
if (!TryGetRecord(moduleId, out _))
|
||||
throw new InvalidOperationException($"Unknown module id: '{moduleId}'.");
|
||||
|
||||
var normalizedId = moduleId.Trim();
|
||||
if (!disabled && !_includeUnlistedEntries && _compositionOptions != null &&
|
||||
!_compositionOptions.ContainsKey(normalizedId))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Module '{normalizedId}' is excluded by the active composition profile.");
|
||||
}
|
||||
|
||||
if (disabled)
|
||||
_disabled.Add(moduleId.Trim());
|
||||
_disabled.Add(normalizedId);
|
||||
else
|
||||
_disabled.Remove(moduleId.Trim());
|
||||
_disabled.Remove(normalizedId);
|
||||
|
||||
await Loader.ApplyAsync(BuildEntries());
|
||||
}
|
||||
@@ -192,8 +257,15 @@ namespace ShrinkContext.AppAdapter
|
||||
{
|
||||
var entries = new List<ShrinkLoaderEntry>();
|
||||
foreach (var record in _modules.Values.OrderBy(m => m.ModuleId, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
CompositionOptions? options = null;
|
||||
_compositionOptions?.TryGetValue(record.ModuleId, out options);
|
||||
if (!_includeUnlistedEntries && _compositionOptions != null && options == null)
|
||||
continue;
|
||||
|
||||
entries.Add(new ShrinkLoaderEntry(record.ModuleId, record.ModuleId, Services,
|
||||
_disabled.Contains(record.ModuleId)));
|
||||
_disabled.Contains(record.ModuleId), options?.Isolate, options?.Intercept));
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user