【问题标题】:Pass a Func<T,bool> as a parameter using reflection?使用反射将 Func<T,bool> 作为参数传递?
【发布时间】:2020-08-26 09:36:30
【问题描述】:

我有一个方法:

public bool DoStuff<T>(T obj) {
  // Do Stuff
  return result;
}

我需要将它作为 Func 参数传递给另一个我在编译时不知道的方法。假设该方法如下所示:

public int Any(Func<int, bool> arg) {
}

或者

public int Any(Func<string, bool> arg) {
}

所以我像这样调用那个方法:

return instance.GetType().InvokeMember(method.Name, BindingFlags.InvokeMethod, null, instance, args);

我想不通的是如何将 DoStuff 的引用封装为 Func,其中我在编译时不知道 T,但在运行时知道它,并将其填充到一个 object[] 作为参数提供给方法调用。

如果有帮助,我正在编写一种简单语言的解释器。 DoStuff 将以简单语言解释 lambda 表达式,调用的方法将是解释器使用者提供的 .NET 函数。

更新

按照 Hans 在 cmets 中提供的链接后(谢谢!)我实现了以下内容:

Type delegateType = typeof(Func<,>).MakeGenericType(new []{argType, typeof(bool)});
MethodInfo delegatedMethod = this.GetType().GetMethod(nameof(DoStuff), BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance);
MethodInfo generic = delegatedMethod.MakeGenericMethod(argType);

Delegate myDelegate = Delegate.CreateDelegate(delegateType, this, generic);
var args = new object[] { myDelegate };

return instance.GetType().InvokeMember(method.Name, BindingFlags.InvokeMethod, null, instance, args);

但是 InvokeMember 调用给了我System.MissingMethodException: 'Method 'MyDomain.Any' not found.'

当我在 Visual Studio 中检查 myDelegate 变量时,它显示:

myDelegate = {Method = {Boolean DoStuff[Func`2](System.Func`2[System.Int32,System.Boolean])} 

它是 args 数组中的唯一元素,我调用的方法签名是:

public int Any(Func<int, bool> arg)

instance 是包含 Any 方法的类的实例,method 是 Any 方法的 MethodInfo。

【问题讨论】:

  • 嗯,这不是泛型的设计目的。我想,您可能想使用dynamic 寻找解决方案?
  • @littlecharva 你能确认pastebin.com/3UxN6Sn4 是你正在尝试做的一个可行的例子吗?
  • @Lause 是的,就是这样。我创建了一个新项目并粘贴到您的代码中,效果很好。然后我开始用我的代码替换您的代码并发现了问题:在我的代码中,我将 Func 作为 argType 传递,而我应该传递 int。它现在完美运行!您是否要发布指向您的 pastebin 的链接作为答案,我会接受。非常感谢您帮我找出错误!

标签: c# .net generics reflection


【解决方案1】:

下面是一些有效的代码:

public class AnyImplementer
{
   public int Any(Func<int, bool> func)
    {
        return func(10)? 1: 0;
    }

  
}

public class DoStuffer
{
    public bool DoStuff<T>(T obj)
    {
        return obj.ToString() != string.Empty;
    }

    public int a(Type argType, AnyImplementer anyImplementer)
    {
        Type delegateType = typeof(Func<,>).MakeGenericType(new[] { argType, typeof(bool) });
        MethodInfo delegatedMethod = this.GetType().GetMethod(nameof(DoStuff), BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance);
        MethodInfo generic = delegatedMethod.MakeGenericMethod(argType);

        Delegate myDelegate = Delegate.CreateDelegate(delegateType, this, generic);
        var args = new object[] { myDelegate };

        return (int)anyImplementer.GetType().InvokeMember("Any", BindingFlags.InvokeMethod, null, anyImplementer, args);
    }
}


public class Program
{
   
    public static void Main(string[] args)
    {
        DoStuffer DoStuffer = new DoStuffer();
        AnyImplementer anyImplementer = new AnyImplementer();
       Console.WriteLine(DoStuffer.a(typeof(int), anyImplementer));
       
    }

    
}

也可以在 https://pastebin.com/raw/3UxN6Sn4 - 这个想法是(基于 OP 的更新和相关问题)使用由通用方法组的方法信息构造的委托创建将方法实例包装到对象中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    相关资源
    最近更新 更多