【问题标题】:MethodInfo.Invoke with a delegate inside Object[] paramsMethodInfo.Invoke 与 Object[] 参数内的委托
【发布时间】:2011-03-07 15:02:59
【问题描述】:

让我试着举一个小例子。

class Session (
    public delegate string CleanBody();
    public static void Execute(string name, string q, CleanBody body) ...

可以这样使用:

Session.Execute("foo", "bar", delegate() { string x="beep"; /* whatever*/ return x; });

但是如果我需要通过 MethodInfo.Invoke 运行——因为在不同的 dll 中没有任何类型的依赖关系。喜欢:

Type type = Type.GetType("Bla.Session, FooSessionDll", true);
MethodInfo methodInfo = type.GetMethod("Execute");

Object [] args = { "foo", "bar", delegate() // Doesn't compile, now that ?
{
    string x="beep"; /* whatever*/ return x;
}

methodInfo.Invoke("Trial Execution :-)", args);

无论应用什么技巧/演员,它都必须以真正的代表身份到达 Execute。实际代表可能有更复杂的签名等。

【问题讨论】:

  • 请更详细地解释您为什么要做如此令人困惑的事情。可能有更好的方法。
  • 不幸的是,使用代表进行类型转换的余地不大。我将不得不首先质疑整体架构。如果没有明确的推理,有些问题可能没有正确的答案。
  • 它没有什么令人困惑的地方 - 只是试图通过 reclection 复制它在接受类型依赖时可能发出的确切调用。就这样。 CLR 中有一些特定的类将委托非常有限地“包装”到对象兼容类中——我只需要更通用的相同变体。所以指向任何私有/内部类的指针也很受欢迎:-) B 端(Session.Execute)是一个巨大的旧包,在 A 端加载的 dll 中仍然有“客户”(执行 MethodInfo.Invoke)。跨度>

标签: c# delegates anonymous-methods


【解决方案1】:
private static class Invoker
{
    private static string Method()
    {
        return "beep";
    }

    public static object Invoke()
    {
        Type type = Type.GetType("Bla.Session, FooSessionDll", true);
        MethodInfo methodInfo = type.GetMethod("Execute");
        Type delegateType = methodInfo.GetParameters()[2].ParameterType;
        Delegate delegateInstance = Delegate.CreateDelegate(delegateType, typeof(Invoker).GetMethod("Method"));
        object[] args = new object[] { "foo", "bar", delegateInstance };
        return methodInfo.Invoke(null, args);
    }
}

【讨论】:

  • 这会从那个“其他”dll 注入一个类型依赖。这不是一个学术问题 :-) 即使 dll B(使用 Session.Execute)根本不存在,dll A(使用 Invoke)也应该编译并运行。任何带有匿名类型的东西都可以吗?
  • @zb_z - 我认为这可能会对您有所帮助,尽管您的问题不是很清楚。
  • 嗯,methodInfo.GetParameters()[2].ParameterType 看起来很有希望,如果有办法将 delegate() { ....} 转换为它。实际涉及的委托使用了它的闭包中的相当多的对象,因此它不能完全被静态方法替换,除非我们进行了我们没有进行的固化:-)
【解决方案2】:

好的,找到了解决方案:Func<<TResult>>,以及整个 Func 模板系列。就我发布的示例而言,将 Execute(...) 的签名转换为:

public static void Execute(string name, string q, Func<string> body) 

在功能上等同于显式命名的委托,即任何类型依赖于它的代码仍然可以使用

Session.Execute("foo", "bar", delegate() { ... });

零代码更改,任何独立的 dll 现在都可以做到:

Func<string> d = delegate() { .....} 

并将其作为普通参数传入Object[]

还有一个帖子在问“Func&lt;&gt; 有什么了不起的地方”——这是 :-)

它允许对使用它的现有代码进行零代码更改,从而打破依赖关系和邪恶的捆绑。一个条件是现有代码使用匿名方法(如示例中)而不是旧式显式委托创建。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 2015-12-17
    • 1970-01-01
    • 2023-04-03
    • 2011-01-12
    相关资源
    最近更新 更多