如何使用 ref struct 参数和未知 return 类型调用内部方法
How to invoke internal method with ref struct parameter and unknown return type
我需要从 System.Text.Json.Serialization.JsonConverter<T>
调用 Read(ref Utf8JsonReader, Type, JsonSerializerOptions)
方法,T
未知。
尝试 1
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var result = converter.GetType()
.GetMethod("Read", BindingFlags.Public | BindingFlags.Instance)
.Invoke(converter, new object[] { reader, type, options });
// ͠ ͠ ͠ ^͠ ͠ ͠
// CS0029: Cannot implicitly convert type
// 'System.Text.Json.Utf8JsonReader' to 'object'
由于 ref 结构不能装箱,我们不能这样做。
delegate object ReadDelegate(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options);
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var result = converter.GetType()
.GetMethod("Read", BindingFlags.Public | BindingFlags.Instance)
.CreateDelegate<ReadDelegate>(converter)(ref reader, type, options);
如果 Read(ref Utf8JsonReader, Type, JsonSerializerOptions)
returns 引用类型(我测试过 int[]
、string
),但值类型(我测试过 int
、int
、 struct
) 产生 System.ArgumentException: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'
delegate object ReadDelegate(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options);
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var instance = Expression.Constant(converter);
var method = converter.GetType().GetMethod("Read", BindingFlags.Public | BindingFlags.Instance);
var parameters = method.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
var call = Expression.Call(instance, method, parameters);
var cast = Expression.TypeAs(call, typeof(object));
var @delegate = Expression.Lambda<ReadDelegate>(cast, parameters);
var result = @delegate.Compile()(ref reader, type, options);
我需要从 System.Text.Json.Serialization.JsonConverter<T>
调用 Read(ref Utf8JsonReader, Type, JsonSerializerOptions)
方法,T
未知。
尝试 1
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var result = converter.GetType()
.GetMethod("Read", BindingFlags.Public | BindingFlags.Instance)
.Invoke(converter, new object[] { reader, type, options });
// ͠ ͠ ͠ ^͠ ͠ ͠
// CS0029: Cannot implicitly convert type
// 'System.Text.Json.Utf8JsonReader' to 'object'
由于 ref 结构不能装箱,我们不能这样做。
delegate object ReadDelegate(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options);
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var result = converter.GetType()
.GetMethod("Read", BindingFlags.Public | BindingFlags.Instance)
.CreateDelegate<ReadDelegate>(converter)(ref reader, type, options);
如果 Read(ref Utf8JsonReader, Type, JsonSerializerOptions)
returns 引用类型(我测试过 int[]
、string
),但值类型(我测试过 int
、int
、 struct
) 产生 System.ArgumentException: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'
delegate object ReadDelegate(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options);
object converter = //Somehow get it;
Utf8JsonReader reader = //Somehow get it;
Type type = //Somehow get it;
JsonSerializerOptions options = //Somehow get them;
var instance = Expression.Constant(converter);
var method = converter.GetType().GetMethod("Read", BindingFlags.Public | BindingFlags.Instance);
var parameters = method.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
var call = Expression.Call(instance, method, parameters);
var cast = Expression.TypeAs(call, typeof(object));
var @delegate = Expression.Lambda<ReadDelegate>(cast, parameters);
var result = @delegate.Compile()(ref reader, type, options);