我有以下类型层次结构:
public abstract class Parent { }
public class Child : Parent
{
public Task SayAsync(string arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
}
我需要实现以下目标:
- 创建
Parent
的任何实例在运行时(这已经通过调用Func<Parent>
来解决,我在代码的其他地方获得了它) - 然后(在该实例上)调用所有
public
方法(始终返回Task
并接受string
作为参数)传入arg
这不是一个常数。
以上内容存在于热路径中,因此为了提高性能,我求助于 Cached Delegates
因此在启动时我将创建委托(delegate),然后在需要时缓存并使用它们。
这是我为 Child
明确完成的示例这是有效的,但我不知道如何让委托(delegate)接受 Parent
(因为我在编译时不知道类型)。
// If I change Child to Parent, I get "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type"
private delegate Task Invoker(Child instance, string arg);
void Main()
{
var instance = new Child(); // This will be obtained by calling a Func<Parent>
var methodWithArg = instance.GetType().GetMethod("SayAsync");
var func = GetDelegateWithArg(methodWithArg);
func(instance, "Foo");
}
private static Invoker GetDelegateWithArg(MethodInfo method)
{
object pointer = null;
return (Invoker)Delegate.CreateDelegate(typeof(Invoker), pointer, method);
}
任何可以帮助我实现目标的想法或替代方案都会受到赞赏。
最佳答案
您可以尝试使用表达式树来生成委托(delegate):
public abstract class Parent { }
public class Child : Parent
{
public Task SayAsync(string arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
}
public delegate Task Invoker(Parent instance, string arg);
class Program
{
static void Main(string[] args)
{
Parent instance = new Child(); // This will be obtained by calling a Func<Parent>
var methodWithArg = instance.GetType().GetMethod("SayAsync");
var func = GetDelegateWithArg(methodWithArg);
func(instance, "Foo");
}
private static Invoker GetDelegateWithArg(MethodInfo method)
{
var instanceParameter = Expression.Parameter(typeof(Parent));
var argParameter = Expression.Parameter(typeof(string));
var body = Expression.Call(
Expression.Convert(instanceParameter, method.DeclaringType),
method,
argParameter);
var lambda = Expression.Lambda<Invoker>(body, instanceParameter, argParameter);
return lambda.Compile();
}
}
生成的委托(delegate)仍然非常快,尽管可能比由 Delegate.CreateDelegate() 方法创建的委托(delegate)慢一点。
关于c# - 如何使 C# Create.Delegate 支持继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40931327/