feat(cordis): 接入上下文组合与模组事务热替换

This commit is contained in:
2026-08-16 23:20:40 +08:00
commit ad256f109b
676 changed files with 52168 additions and 0 deletions
@@ -0,0 +1,11 @@
using System;
namespace ShrinkNetwork
{
public interface IShrinkNetworkSerializer
{
byte[] Serialize(object value);
object Deserialize(byte[] payload, Type type);
T Deserialize<T>(byte[] payload);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f1353960f8123d4f96a4815b3627051
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,29 @@
#nullable enable
using System;
using System.Text;
using Newtonsoft.Json;
namespace ShrinkNetwork
{
public sealed class ShrinkJsonNetworkSerializer : IShrinkNetworkSerializer
{
private static readonly JsonSerializerSettings Settings = new()
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Include,
Formatting = Formatting.None
};
public byte[] Serialize(object value)
=> Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value, Settings));
public object Deserialize(byte[] payload, Type type)
=> JsonConvert.DeserializeObject(Encoding.UTF8.GetString(payload), type, Settings)
?? throw new JsonSerializationException($"Failed to deserialize payload into {type.FullName}.");
public T Deserialize<T>(byte[] payload)
=> JsonConvert.DeserializeObject<T>(Encoding.UTF8.GetString(payload), Settings)
?? throw new JsonSerializationException($"Failed to deserialize payload into {typeof(T).FullName}.");
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2a0f828927e72b4b9d1542cc8a24b8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,150 @@
#nullable enable
using System;
using System.Linq;
using System.Reflection;
namespace ShrinkNetwork
{
public sealed class ShrinkMessagePackNetworkSerializer : IShrinkNetworkSerializer
{
private readonly MethodInfo _serializeMethod;
private readonly MethodInfo _deserializeMethod;
private readonly object? _serializerOptions;
public ShrinkMessagePackNetworkSerializer()
{
var serializerType = Type.GetType("MessagePack.MessagePackSerializer, MessagePack");
if (serializerType == null)
{
throw new InvalidOperationException(
"MessagePack assembly was not found. Please install MessagePack-CSharp before using ShrinkMessagePackNetworkSerializer.");
}
_serializerOptions = ResolveSerializerOptions(serializerType.Assembly);
var serializeMethod = serializerType
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m =>
{
if (m.Name != "Serialize")
return false;
var parameters = m.GetParameters();
return parameters.Length >= 2 &&
parameters[0].ParameterType == typeof(Type) &&
parameters[1].ParameterType == typeof(object);
});
var deserializeMethod = serializerType
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m =>
{
if (m.Name != "Deserialize")
return false;
var parameters = m.GetParameters();
return parameters.Length >= 2 &&
parameters[0].ParameterType == typeof(Type) &&
(parameters[1].ParameterType == typeof(byte[]) ||
parameters[1].ParameterType == typeof(ReadOnlyMemory<byte>));
});
if (serializeMethod == null || deserializeMethod == null)
throw new MissingMethodException("MessagePack serialize/deserialize API not found.");
_serializeMethod = serializeMethod;
_deserializeMethod = deserializeMethod;
}
public byte[] Serialize(object value)
{
if (value == null)
return Array.Empty<byte>();
var parameters = BuildParameters(_serializeMethod, value.GetType(), value, _serializerOptions);
return (byte[])_serializeMethod.Invoke(null, parameters)!;
}
public object Deserialize(byte[] payload, Type type)
{
payload ??= Array.Empty<byte>();
var parameters = BuildParameters(_deserializeMethod, type, payload, _serializerOptions);
return _deserializeMethod.Invoke(null, parameters)
?? throw new InvalidOperationException($"MessagePack returned null for type {type.FullName}.");
}
public T Deserialize<T>(byte[] payload)
{
return (T)Deserialize(payload, typeof(T));
}
private static object?[] BuildParameters(MethodInfo method, Type type, object valueOrBytes, object? serializerOptions)
{
var parameters = method.GetParameters();
var args = new object?[parameters.Length];
if (parameters.Length > 0)
args[0] = type;
if (parameters.Length > 1)
args[1] = ConvertPrimaryArgument(parameters[1].ParameterType, valueOrBytes);
for (var i = 2; i < parameters.Length; i++)
{
args[i] = ResolveAdditionalArgument(parameters[i], serializerOptions);
}
return args;
}
private static object? ResolveAdditionalArgument(ParameterInfo parameter, object? serializerOptions)
{
if (serializerOptions != null && parameter.ParameterType.IsInstanceOfType(serializerOptions))
return serializerOptions;
return parameter.HasDefaultValue
? parameter.DefaultValue
: GetDefault(parameter.ParameterType);
}
private static object ConvertPrimaryArgument(Type parameterType, object value)
{
if (parameterType == typeof(ReadOnlyMemory<byte>) && value is byte[] bytes)
return new ReadOnlyMemory<byte>(bytes);
return value;
}
private static object? ResolveSerializerOptions(Assembly serializerAssembly)
{
var contractlessResolverType = serializerAssembly.GetType("MessagePack.Resolvers.ContractlessStandardResolver");
if (contractlessResolverType != null)
{
var optionsField = contractlessResolverType.GetField("Options",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
var options = optionsField?.GetValue(null);
if (options != null)
return options;
var instanceField = contractlessResolverType.GetField("Instance",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
var instance = instanceField?.GetValue(null);
if (instance != null)
{
var optionsType = serializerAssembly.GetType("MessagePack.MessagePackSerializerOptions");
var standardProperty = optionsType?.GetProperty("Standard", BindingFlags.Public | BindingFlags.Static);
var standardOptions = standardProperty?.GetValue(null);
var withResolverMethod = optionsType?.GetMethod("WithResolver", BindingFlags.Public | BindingFlags.Instance);
var resolvedOptions = withResolverMethod?.Invoke(standardOptions, new[] { instance });
if (resolvedOptions != null)
return resolvedOptions;
}
}
return null;
}
private static object? GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88c6239e9fc049f43b2999d7311eec1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: