【发布时间】:2021-11-29 07:56:54
【问题描述】:
我很抱歉地问,我怎样才能使用其他那个 method.Invoke 来调用方法,因为有些文章说,method.Invoke 的性能较慢。 实际上我使用的是 .NET Core 3.1。
例如,我有一个类似这样的结构代码。
public class Message { }
public class MyMessageType : Message { }
public class MyMessageResult
{
public bool Status { get; set; }
public DateTime Date => DateTime.Now;
}
public interface IEncapsulatedMessageHandlerV2<T, TResult> where T : class
{
Task<TResult> HandleMessageResultAsync(T message);
}
public abstract class EncasulatedMessageHandlerV2<T, TResult> : IEncapsulatedMessageHandlerV2<T, TResult> where T : Message
{
public abstract Task<TResult> HandleMessageResultExecAsync(T message);
async Task<TResult> IEncapsulatedMessageHandlerV2<T, TResult>.HandleMessageResultAsync(T message)
{
var msg = message as T;
if (msg != null)
return await HandleMessageResultExecAsync(msg);
return default;
}
}
public class HandlerV2 : EncasulatedMessageHandlerV2<MyMessageType, MyMessageResult>
{
public override Task<MyMessageResult> HandleMessageResultExecAsync(MyMessageType message)
{
Console.WriteLine("Yo Async!");
return Task.FromResult(new MyMessageResult
{
Status = true
});
}
}
我可以使用method.Invoke成功调用
static TResponse UsingMethodInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var type = typeof(IEncapsulatedMessageHandlerV2<MyMessageType, MyMessageResult>);
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var method = type.GetMethod("HandleMessageResultAsync");
var tsk = (Task<TResponse>)method.Invoke(instance, new[] { new MyMessageType() });
var result = tsk.GetAwaiter().GetResult();
return result;
}
我也尝试使用Dynamic,不幸的是他们不能通过抽象HandleMessageResultAsync调用,而只能通过实现类HandleMessageResultExecAsync
static TResponse UsingDynamicInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var tsk = (Task<TResponse>)((dynamic)instance).HandleMessageResultExecAsync(new MyMessageType());
var result = tsk.GetAwaiter().GetResult();
return result;
}
我被 stackoverflow Speeding up Reflection Invoke C#/.NET 跟踪,我被卡住了
static void ActivatorMyMessageResultAsnc()
{
var type = typeof(HandlerV2);
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("HandleMessageResultAsync", BindingFlags.Instance | BindingFlags.Public);
var originalType = type;
// Loop until we hit the type we want.
while (!(type.IsGenericType) || type.GetGenericTypeDefinition() != typeof(EncasulatedMessageHandlerV2<,>))
{
type = type.BaseType;
if (type == null)
throw new ArgumentOutOfRangeException("type");
}
var messageType = type.GetGenericArguments()[0]; // MyMessageType
// Use expression to create a method we can.
var instExpr = Expression.Parameter(typeof(object), "instance");
var paramExpr = Expression.Parameter(typeof(Message), "message");
// (Handler)instance;
var instCastExpr = Expression.Convert(instExpr, originalType);
// (MyMessageType)message
var castExpr = Expression.Convert(paramExpr, messageType);
// ((Handler)inst).HandleMessage((MyMessageType)message)
var invokeExpr = Expression.Call(instCastExpr, method, castExpr); // <--- this give me error
// i'm stuck, i don't know what should i do next
////// Assume this is build from MakeGeneric too
////var delType = typeof(Func<object, Message, Task<MessageResult>>);
//var lambda = Expression.Lambda<Func<object, Message, Task<object>>>(invokeExpr, instExpr, paramExpr);
//var compiled = lambda.Compile();
//Func<Message, Task<object>> hook = x => compiled(instance, x);
或者,有没有其他方法可以通过动态方式调用方法,这比方法更快。调用
提前致谢,
PS:对不起我的英语不好
【问题讨论】:
-
你可以通过稍微改变你的设计来避免这一切。只需引入
IEncapsulatedMessageHandlerV2扩展的非泛型接口。
标签: c# methods expression-trees invoke method-call