c# - 如何使 C# Create.Delegate 支持继承?

标签 c# .net reflection delegates

我有以下类型层次结构:

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/

相关文章:

c# - 更高效的循环?

.net - 如何在 Visual C++ .net 中将一个项目从一个列表框转移到另一个

java - 构造时通过反射获取Java中的静态实例名称

c# - 如何通过反射忽略父接口(interface)上的事件来获取类型的事件

java - 使用Java反射加载接口(interface)

c# - .Net Powerpoint 组件

c# - 在 C# 中使用抽象类

c# - 从 JObject 中删除重复项

c# - Entity Framework 中的多个自引用关系

c# - 如何在 .Net Core 中设置默认内部版本号