从MethodInfo构建代理? [英] Builds a Delegate from MethodInfo?

查看:140
本文介绍了从MethodInfo构建代理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Google上搜索和着陆后,阅读了这个其他问题

After googling and landing on SO and having read this other question


是否可以从MethodInfo 构建正确的代理,如果您不知道数字或类型参数在编译时?

Is it possible to build a correct Delegate from a MethodInfo if you didn't know the number or types of parameters at compile time?

更多信息:这可以优雅地完成,而不使用Reflection.Emit或类型构建器?

More on this: can this be done elegantly without the use of Reflection.Emit or type builders?

这对我来说是一个很大的障碍,因为Delegate.CreateDelegate要求我将正确的Delegate类型指定为第一个参数,否则会抛出异常或调用不正确的方法。

This is sorta a bummer for me because Delegate.CreateDelegate requires me to specify the correct Delegate type as the first parameter or else it would throw exceptions or invoke an incorrect method.

我正在构建一些忍者齿轮,这将有助于很多...谢谢!

I'm building some ninja gears and this would helps a lot... Thanks!

这是一个通用的解决方案:

/// <summary>
/// Builds a Delegate instance from the supplied MethodInfo object and a target to invoke against.
/// </summary>
public static Delegate ToDelegate(MethodInfo mi, object target)
{
    if (mi == null) throw new ArgumentNullException("mi");

    Type delegateType;

    var typeArgs = mi.GetParameters()
        .Select(p => p.ParameterType)
        .ToList();

    // builds a delegate type
    if (mi.ReturnType == typeof(void)) {
        delegateType = Expression.GetActionType(typeArgs.ToArray());

    } else {
        typeArgs.Add(mi.ReturnType);
        delegateType = Expression.GetFuncType(typeArgs.ToArray());
    }

    // creates a binded delegate if target is supplied
    var result = (target == null)
        ? Delegate.CreateDelegate(delegateType, mi)
        : Delegate.CreateDelegate(delegateType, target, mi);

    return result;
}






注意:我正在构建一个Silverlight应用程序,它将替代一个内置的JavaScript应用程序,其中我有多个Javascript接口调用到相同的Silverlight [ScriptableMember]方法。


Note: I am building a Silverlight application that would replace a built-years-ago javascript application in which I have multiple Javascript interfaces that calls into the same Silverlight [ScriptableMember] method.

所有这些遗留的JS接口都需要被支持,以及访问新功能的新界面,所以自动设置JS界面并将调用委托到正确的Silverlight方法的东西将有助于加快工作速度。

All those legacy JS interfaces need to be supported as well as new interface for accessing new features, so something that automatically setups the JS interface and "delegates" the call to the right Silverlight method would helps speed up work a lot.

我不能在这里发布代码,所以这是总结。

I can't post code here, so that's the summary.

推荐答案

说实话,如果你在编译时不知道类型,那么创建一个代表就没有很大的好处。您不想使用 DynamicInvoke ;它会像反射一样慢。主要的例外是当阴影中有一个委托类型潜伏时,例如订阅一个事件时 - 在这种情况下, EventInfo 使这个可用。

To be honest, if you don't know the type at compile time, there isn't a huge amount of benefit in creating a Delegate. You don't want to use DynamicInvoke; it will be about as slow as reflection. The main exception to this is when there is a delegate-type lurking in the shadows, for example when subscribing to an event - in which case EventInfo makes this available.

有关信息,请在表达式中的.NET 3.5中,有:

For info, in .NET 3.5 on Expression, there is:

Expression.GetActionType(params Type[] typeArgs);
Expression.GetFuncType(params Type[] typeArgs)

这可能有助于一个程度:

That might help to an extent:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
static class Program {
    static void Main() {
        DoStuff("Test1");
        DoStuff("Test2");
    }
    static void DoStuff(string methodName) {
        MethodInfo method = typeof(Program).GetMethod(methodName);
        List<Type> args = new List<Type>(
            method.GetParameters().Select(p => p.ParameterType));
        Type delegateType;
        if (method.ReturnType == typeof(void)) {
            delegateType = Expression.GetActionType(args.ToArray());
        } else {
            args.Add(method.ReturnType);
            delegateType = Expression.GetFuncType(args.ToArray());
        }
        Delegate d = Delegate.CreateDelegate(delegateType, null, method);
        Console.WriteLine(d);
    }
    public static void Test1(int i, DateTime when) { }
    public static float Test2(string x) { return 0; }
}

这篇关于从MethodInfo构建代理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆