首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从MethodInfo构建代表?

从MethodInfo构建代表?
EN

Stack Overflow用户
提问于 2009-07-14 10:28:01
回答 3查看 13.6K关注 0票数 32

在搜索并登陆SO并阅读this other question之后

如果

在编译时不知道参数的数量或类型,那么是否有可能从MethodInfo 构建正确的代理?

关于这一点的更多信息:如果不使用Reflection.Emit或类型构建器,是否可以很好地完成这一任务?

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

我在做忍者齿轮这会有很大帮助..。谢谢!

这里有一个通用的解决方案:

代码语言:javascript
复制
/// <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;
}

Note:我正在构建一个Silverlight应用程序,它将取代一个构建多年前的javascript应用程序,在这个应用程序中,我有多个Javascript接口,它们调用同一个Silverlight ScriptableMember方法。

所有这些遗留的JS接口以及访问新特性的新接口都需要支持,因此自动设置JS接口并“委托”对正确的Silverlight方法的调用将有助于大大加快工作速度。

我不能在这里贴代码,这就是总结。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-07-14 10:36:04

老实说,如果您在编译时不知道类型,那么创建Delegate没有很大的好处。您不想使用DynamicInvoke;它将与反射一样慢。这方面的主要例外是,隐藏在阴影中的是委托类型,例如当订阅事件时--在这种情况下,EventInfo使其可用。

有关信息,在.NET 3.5 on Expression中,有:

代码语言:javascript
复制
Expression.GetActionType(params Type[] typeArgs);
Expression.GetFuncType(params Type[] typeArgs)

这可能在一定程度上有助于:

代码语言:javascript
复制
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; }
}
票数 22
EN

Stack Overflow用户

发布于 2010-12-28 08:43:02

为什么这么复杂?

代码语言:javascript
复制
public static Delegate CreateDelegate(this MethodInfo method)
{
    return Delegate.CreateDelegate
    (
        Expression.GetDelegateType
        (
            method.GetParameters()
                .Select(p => p.ParameterType)
                .Concat(new Type[] { method.ReturnType })
                .ToArray()
        ),
        null,
        method
    );   
}

附带注意:我将此方法前缀为“Create.”。“到.”令人困惑的是,当你认为这是一种转变时,你会感到困惑。

票数 9
EN

Stack Overflow用户

发布于 2009-07-14 10:34:10

如果您事先不知道参数的数量或类型,那么这可能意味着您不知道要创建的委托类型?

如果是这样的话,你就被困在了绝对普通的案子里。

但是,对于大多数常见的情况(没有ref/out参数,很少有足够的参数来使用现有的类型),您可以使用FuncAction委托。(.NET 4.0有大量参数的Func/Action类型,因此您只需要担心out/ref参数。)如果方法具有非空返回类型,则使用Func,否则使用Action。根据参数的数量,确定使用哪种类型。

代码语言:javascript
复制
static readonly Type[] FuncTypes = { typeof(Func), 
    typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), /* etc */ };

使用Type.MakeGenericType使用参数类型和返回类型来获得正确的委托类型,那么Delegate.CreateDelegate应该可以工作。

我现在没有时间去做样品,但是如果你想让我稍后再做的话,请告诉我。

一个问题:你打算如何使用这个代表?其他的东西需要知道如何执行,当然.

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1124563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档