Если ничего не помогает, вы можете сделать это с помощью скомпилированных выражений:
class Program
{
private delegate object ReadDelegate(JsonConverter converter, ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options);
public static void Main()
{
var converter = new FooConverter();
var converterType = converter.GetType();
var typeOfT = typeof(int);
var converterParameter = Expression.Parameter(typeof(JsonConverter));
var readerParameter = Expression.Parameter(typeof(Utf8JsonReader).MakeByRefType());
var typeToConvertParameter = Expression.Parameter(typeof(Type));
var optionsParameter = Expression.Parameter(typeof(JsonSerializerOptions));
var readMethodInfo = converterType.GetMethod("Read");
var castConverter = Expression.Convert(converterParameter, converterType);
var call = Expression.Call(
castConverter,
readMethodInfo,
readerParameter,
typeToConvertParameter,
optionsParameter);
var castResult = Expression.Convert(call, typeof(object));
var lambda = Expression.Lambda<ReadDelegate>(
castResult,
converterParameter,
readerParameter,
typeToConvertParameter,
optionsParameter).Compile();
var reader = new Utf8JsonReader();
var result = lambda(converter, ref reader, typeof(int), new JsonSerializerOptions());
}
}
public class FooConverter : JsonConverter<int>
{
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => 3;
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) => throw new NotImplementedException();
}
Убедитесь, что вы кешируете lambda
- это относительно дорого создавать, но очень дешево вызывать.
Это, по сути, создает метод во время выполнения, который выглядит примерно так:
public object Lambda(
JsonConverter converterParameter,
ref Utf8JsonReader readerParameter,
Type typeToConvertParameter,
JsonSerializerOptions optionsParameter)
{
var castConverter = (FooConverter)converterParameter;
var call = castConverter.Read(ref readerParameter, typeToConvertParameter, optionsParameter);
return (object)call;
}
Тем не менее, вам, вероятно, лучше написать обобщенный метод c, а затем вызвать его с отражением, а не с помощью отражения для непосредственного вызова метода Read
:
class Program
{
public static void Main()
{
var converter = new FooConverter();
var typeOfT = typeof(int);
var methodInfo = typeof(Program).GetMethod("Foo").MakeGenericMethod(typeOfT);
var result = methodInfo.Invoke(null, new[] { converter });
}
public static T Foo<T>(JsonConverter<T> converter)
{
var reader = new Utf8JsonReader();
return converter.Read(ref reader, typeof(int), new JsonSerializerOptions());
}
}
По общему признанию, это просто перемещает проблему, но это может работать для вас.