feat(cordis): 接入上下文组合与模组事务热替换
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ShrinkModFramework
|
||||
{
|
||||
internal interface IShrinkOwnedRegistry
|
||||
{
|
||||
void RemoveOwnedEntries(string ownerModId);
|
||||
}
|
||||
|
||||
public sealed class ShrinkModRegistry<T> : IShrinkOwnedRegistry
|
||||
{
|
||||
private readonly Dictionary<string, ShrinkRegistryEntry<T>> _entries = new();
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
internal ShrinkModRegistry(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
throw new ArgumentException("注册表名称不能为空。", nameof(name));
|
||||
|
||||
Name = name.Trim();
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<ShrinkRegistryEntry<T>> Entries => _entries.Values.ToArray();
|
||||
|
||||
public void Register(string ownerModId, string key, T value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ownerModId))
|
||||
throw new ArgumentException("归属模组 ID 不能为空。", nameof(ownerModId));
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
throw new ArgumentException("注册键不能为空。", nameof(key));
|
||||
|
||||
key = key.Trim();
|
||||
if (_entries.ContainsKey(key))
|
||||
throw new InvalidOperationException($"注册表 '{Name}' 中已存在键 '{key}'。");
|
||||
|
||||
_entries.Add(key, new ShrinkRegistryEntry<T>(ownerModId.Trim(), key, value));
|
||||
}
|
||||
|
||||
public bool Contains(string key) => !string.IsNullOrWhiteSpace(key) && _entries.ContainsKey(key.Trim());
|
||||
|
||||
public bool TryGet(string key, out T value)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(key) && _entries.TryGetValue(key.Trim(), out var entry))
|
||||
{
|
||||
value = entry.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetEntry(string key, out ShrinkRegistryEntry<T> entry)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(key))
|
||||
return _entries.TryGetValue(key.Trim(), out entry);
|
||||
|
||||
entry = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
void IShrinkOwnedRegistry.RemoveOwnedEntries(string ownerModId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ownerModId))
|
||||
return;
|
||||
|
||||
var keys = _entries
|
||||
.Where(pair => string.Equals(pair.Value.OwnerModId, ownerModId, StringComparison.Ordinal))
|
||||
.Select(pair => pair.Key)
|
||||
.ToArray();
|
||||
foreach (var key in keys)
|
||||
_entries.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ShrinkRegistryEntry<T>
|
||||
{
|
||||
public string OwnerModId { get; }
|
||||
public string Key { get; }
|
||||
public T Value { get; }
|
||||
|
||||
public ShrinkRegistryEntry(string ownerModId, string key, T value)
|
||||
{
|
||||
OwnerModId = ownerModId;
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cb75a17a6ee08f479d0be1fe145307f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ShrinkModFramework
|
||||
{
|
||||
public sealed class ShrinkModRegistryManager
|
||||
{
|
||||
private readonly Dictionary<string, object> _registries = new();
|
||||
|
||||
public ShrinkModRegistry<T> GetOrCreateRegistry<T>(string name)
|
||||
{
|
||||
var compositeKey = BuildCompositeKey(typeof(T), name);
|
||||
if (_registries.TryGetValue(compositeKey, out var existing))
|
||||
return (ShrinkModRegistry<T>)existing;
|
||||
|
||||
var registry = new ShrinkModRegistry<T>(name);
|
||||
_registries.Add(compositeKey, registry);
|
||||
return registry;
|
||||
}
|
||||
|
||||
public bool TryGetRegistry<T>(string name, out ShrinkModRegistry<T> registry)
|
||||
{
|
||||
var compositeKey = BuildCompositeKey(typeof(T), name);
|
||||
if (_registries.TryGetValue(compositeKey, out var existing))
|
||||
{
|
||||
registry = (ShrinkModRegistry<T>)existing;
|
||||
return true;
|
||||
}
|
||||
|
||||
registry = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void Clear() => _registries.Clear();
|
||||
|
||||
internal void RemoveOwnedEntries(string ownerModId)
|
||||
{
|
||||
foreach (var registry in _registries.Values)
|
||||
{
|
||||
if (registry is IShrinkOwnedRegistry ownedRegistry)
|
||||
ownedRegistry.RemoveOwnedEntries(ownerModId);
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildCompositeKey(Type type, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
throw new ArgumentException("注册表名称不能为空。", nameof(name));
|
||||
|
||||
return $"{type.AssemblyQualifiedName}::{name.Trim()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa8f924fbddf4e544a8531969765b217
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user