C#:返回给定对象和方法名称的委托

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/783108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:58:28  来源:igfitidea点击:

C#: Return a delegate given an object and a method name

c#reflection

提问by Austin Salonen

Suppose I'm given an object and a string that holds a method name, how can I return a delegate to that method (of that method?) ?

假设我得到一个对象和一个包含方法名称的字符串,我如何将委托返回给该方法(该方法的?)?

Example:

例子:

MyDelegate GetByName(ISomeObject obj, string methodName)
{
    ...
    return new MyDelegate(...);
}

ISomeObject someObject = ...;
MyDelegate myDelegate = GetByName(someObject, "ToString");

//myDelegate would be someObject.ToString

Thanks in advance.

提前致谢。

One more thing -- I really don't want to use a switch statement even though it would work but be a ton of code.

还有一件事——我真的不想使用 switch 语句,即使它可以工作但需要大量代码。

采纳答案by Jon Skeet

You'll need to use Type.GetMethodto get the right method, and Delegate.CreateDelegateto convert the MethodInfointo a delegate. Full example:

您需要使用Type.GetMethod来获取正确的方法,并将Delegate.CreateDelegate其转换MethodInfo为委托。完整示例:

using System;
using System.Reflection;

delegate string MyDelegate();

public class Dummy
{
    public override string ToString()
    {
        return "Hi there";
    }
}

public class Test
{
    static MyDelegate GetByName(object target, string methodName)
    {
        MethodInfo method = target.GetType()
            .GetMethod(methodName, 
                       BindingFlags.Public 
                       | BindingFlags.Instance 
                       | BindingFlags.FlattenHierarchy);

        // Insert appropriate check for method == null here

        return (MyDelegate) Delegate.CreateDelegate
            (typeof(MyDelegate), target, method);
    }

    static void Main()
    {
        Dummy dummy = new Dummy();
        MyDelegate del = GetByName(dummy, "ToString");

        Console.WriteLine(del());
    }
}

Mehrdad's comment is a great one though - if the exceptions thrown by this overload of Delegate.CreateDelegateare okay, you can simplify GetByNamesignificantly:

不过,Mehrdad 的评论很棒——如果Delegate.CreateDelegate的这个重载抛出的异常没问题,你可以GetByName显着简化:

    static MyDelegate GetByName(object target, string methodName)
    {
        return (MyDelegate) Delegate.CreateDelegate
            (typeof(MyDelegate), target, methodName);
    }

I've never used this myself, because I normally do other bits of checking after finding the MethodInfoexplicitly - but where it's suitable, this is really handy :)

我自己从来没有使用过这个,因为我通常会在MethodInfo明确找到后进行其他检查- 但在合适的地方,这真的很方便:)

回答by Mehrdad Afshari

static MyDelegate GetByName(object obj, string methodName)
{
    return () => obj.GetType().InvokeMember(methodName, 
        System.Reflection.BindingFlags.InvokeMethod, null, obj, null); 
}

回答by JoshBerke

Even easier is to use:

使用起来更简单:

    public static MyDelegate GetByName(object target, string methodName)
    {
        return (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), 
               target, methodName);
    }

Notice that CreateDelegate has an overload which takes the methodName for you. This was done with .net 3.5 Sp1

请注意, CreateDelegate 有一个重载,它为您获取 methodName。这是用 .net 3.5 Sp1 完成的