feat(mod): 完成外部 DLL 事务热替换

This commit is contained in:
2026-08-16 23:52:53 +08:00
parent ad256f109b
commit de5ab449cd
23 changed files with 416 additions and 18 deletions
@@ -17,6 +17,14 @@ namespace ShrinkModFramework
public Assembly Assembly;
}
internal sealed class RevisionState
{
public Dictionary<string, ExternalAssemblyRevision> Current =
new(StringComparer.OrdinalIgnoreCase);
public Dictionary<string, string> Known =
new(StringComparer.OrdinalIgnoreCase);
}
private static readonly Dictionary<string, ExternalAssemblyRevision> CurrentAssemblyRevisions =
new(StringComparer.OrdinalIgnoreCase);
private static readonly HashSet<Assembly> ExternalAssemblyHistory = new();
@@ -101,6 +109,12 @@ namespace ShrinkModFramework
.ToArray())
{
CurrentAssemblyRevisions.Remove(missingPath);
var assemblyName = Path.GetFileNameWithoutExtension(missingPath);
if (KnownAssemblyFiles.TryGetValue(assemblyName, out var knownPath) &&
string.Equals(knownPath, missingPath, StringComparison.OrdinalIgnoreCase))
{
KnownAssemblyFiles.Remove(assemblyName);
}
}
return CurrentAssemblyRevisions.Values
@@ -112,6 +126,35 @@ namespace ShrinkModFramework
internal static bool IsExternalAssembly(Assembly assembly) =>
assembly != null && ExternalAssemblyHistory.Contains(assembly);
internal static RevisionState CaptureState()
{
return new RevisionState
{
Current = CurrentAssemblyRevisions.ToDictionary(
pair => pair.Key,
pair => pair.Value,
StringComparer.OrdinalIgnoreCase),
Known = KnownAssemblyFiles.ToDictionary(
pair => pair.Key,
pair => pair.Value,
StringComparer.OrdinalIgnoreCase)
};
}
internal static void RestoreState(RevisionState state)
{
if (state == null)
throw new ArgumentNullException(nameof(state));
CurrentAssemblyRevisions.Clear();
foreach (var pair in state.Current)
CurrentAssemblyRevisions[pair.Key] = pair.Value;
KnownAssemblyFiles.Clear();
foreach (var pair in state.Known)
KnownAssemblyFiles[pair.Key] = pair.Value;
}
internal static bool TryGetCurrentRevision(Assembly assembly, out string revision)
{
foreach (var current in CurrentAssemblyRevisions.Values)
@@ -138,7 +181,6 @@ namespace ShrinkModFramework
internal static void ResetForTesting()
{
CurrentAssemblyRevisions.Clear();
ExternalAssemblyHistory.Clear();
KnownAssemblyFiles.Clear();
if (_resolveRegistered)
{
@@ -147,6 +189,12 @@ namespace ShrinkModFramework
}
}
internal static void ResetForDomainReload()
{
ResetForTesting();
ExternalAssemblyHistory.Clear();
}
private static string ComputeSha256(byte[] bytes)
{
using var sha256 = SHA256.Create();