如何从泛型接口构建调用方法的表达式树



我很抱歉地问,我如何使用其他方法调用方法。调用,因为有些文章说,方法。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
});
}
}

并且我可以成功调用using method。调用

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;
}

我也尝试使用动态,不幸的是他们不能通过抽象调用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加速反射调用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: Sorry for my English Bad

我有一个类似的问题,我试图解决一会儿。我深入研究了Net Core代码库,发现了一个类,它对于在运行时调用方法非常有用,而不需要强类型。

https://github.com/dotnet/extensions/blob/ff87989d893b000aac1bfef0157c92be1f04f714/shared/Microsoft.Extensions.ObjectMethodExecutor.Sources/ObjectMethodExecutor.cs

objectmethodexexecutor允许您使用对象的名称调用对象的方法。使用的一个例子是:

var methodInfo = [myInterface].GetMethod("[method-you-want-call]");
var classTypeInfo = [myClass].GetTypeInfo();
var executor = ObjectMethodExecutor.Create(methodInfo, classTypeInfo);
await executor.ExecuteAsync(handler, new[] { [data-you-want-to-pass-to-your-object] });

在SignalR代码库中广泛使用,用于将SignalR消息与集线器上的内部方法相匹配。它经过了大量优化,并且具有允许调用异步方法的额外好处

最新更新