Skip to content

Instantly share code, notes, and snippets.

@jcasts
Created January 21, 2026 16:29
Show Gist options
  • Select an option

  • Save jcasts/fa6a3733c5038a7209e419ce6aa66d60 to your computer and use it in GitHub Desktop.

Select an option

Save jcasts/fa6a3733c5038a7209e419ce6aa66d60 to your computer and use it in GitHub Desktop.
private static Func<object?, CancellationToken, byte[]> GetMessagePackSerializeFunc(
MessagePackSerializer serializer,
Type type,
ITypeShape typeShape)
{
// public byte[] Serialize<T>(in T? value, ITypeShape<T> shape, CancellationToken cancellationToken = default)
MethodInfo serialize = GetMethod(nameof(MessagePackSerializer.Serialize), type, new Type?[] { null, typeof(ITypeShape<>), typeof(CancellationToken) });
ConstantExpression instanceExpression = Expression.Constant(serializer);
ParameterExpression param1 = Expression.Parameter(typeof(object), "value");
ConstantExpression param2 = Expression.Constant(typeShape);
ParameterExpression param3 = Expression.Parameter(typeof(CancellationToken), "cancellationToken");
MethodCallExpression body = Expression.Call(
instanceExpression,
serialize,
type.IsValueType ? Expression.Unbox(param1, type) : Expression.Convert(param1, type),
param2,
param3);
return Expression.Lambda<Func<object?, CancellationToken, byte[]>>(body, param1, param3).Compile(false);
}
private static Func<ReadOnlySequence<byte>, CancellationToken, object?> GetMessagePackDeserializeFunc(
MessagePackSerializer serializer,
Type type,
ITypeShape typeShape)
{
// public T? Deserialize<T>(scoped in ReadOnlySequence<byte> buffer, ITypeShape<T> shape, CancellationToken cancellationToken = default)
MethodInfo deserialize = GetMethod(nameof(MessagePackSerializer.Deserialize), type, new Type?[] { typeof(ReadOnlySequence<byte>), typeof(ITypeShape<>), typeof(CancellationToken) });
ConstantExpression instanceExpression = Expression.Constant(serializer);
ParameterExpression param1 = Expression.Parameter(typeof(ReadOnlySequence<byte>), "value");
ConstantExpression param2 = Expression.Constant(typeShape);
ParameterExpression param3 = Expression.Parameter(typeof(CancellationToken), "cancellationToken");
UnaryExpression body = Expression.Convert(Expression.Call(instanceExpression, deserialize, param1, param2, param3), typeof(object));
return Expression.Lambda<Func<ReadOnlySequence<byte>, CancellationToken, object?>>(body, param1, param3).Compile(false);
}
// null is generic type marker.
private static MethodInfo GetMethod(string methodName, Type type, Type?[] parameters)
{
return typeof(MessagePackSerializer).GetRuntimeMethods().Single(x =>
{
if (methodName != x.Name)
{
return false;
}
ParameterInfo[] ps = x.GetParameters();
if (ps.Length != parameters.Length)
{
return false;
}
for (int i = 0; i < ps.Length; i++)
{
var parameterType = ps[i].ParameterType;
if (parameterType.IsByRef)
{
parameterType = parameterType.GetElementType()!;
}
if (parameters[i] == null && parameterType.IsGenericParameter)
{
continue;
}
if (parameterType.IsGenericType && parameterType.ContainsGenericParameters && parameters[i]?.ContainsGenericParameters == true)
{
parameterType = parameterType.GetGenericTypeDefinition();
}
if (parameterType != parameters[i])
{
return false;
}
}
return true;
})
.MakeGenericMethod(type);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment