从方法引用C#获取methodinfo

Bog*_*ets 18 .net c# reflection typeof methodinfo

typeof当我们想要获取指定类型的Type实例时,我们可以使用C#关键字.但是,如果我想MethodInfo通过它的参考得到一个方法,我可以使用什么?

例如,我有一个简单的控制台应用程序.它包含Program.Main方法.我希望MethodInfo通过使用类似的东西methodinfoof(Program.Main).我有这个问题,因为方法名称可能会改变,所以我不能只使用Type.GetMethodInfo(string MethodName)它.

我有大约10 000种方法可供我使用MethodInfo,因此在我的方法中添加任何自定义属性或其他任何方法都不是解决方案.

Chr*_*ney 16

轻微改编以前发布的答案,但这篇博文似乎达到了你的要求; http://blog.functionalfun.net/2009/10/getting-methodinfo-of-generic-method.html

样本用法如下;

var methodInfo = SymbolExtensions.GetMethodInfo(() => Program.Main());
Run Code Online (Sandbox Code Playgroud)

原来的答案就是这个问题; /sf/answers/639281191/

  • @Jason:你失去了我 - 你有什么意义?上面张贴的代码*确实*有效,并准确提供原始问题所要求的内容.Program.Main的MethodInfo.如果你想要带有string []参数的重载的MethodInfo,那么就像这样调用它; SymbolExtensions.GetMethodInfo(()=> Program.Main(null); (2认同)

Dmi*_* S. 12

您可以将表达式树用于非静态方法.这是一个例子.

using System.Linq.Expressions;
using System.Reflection;

public static class MethodInfoHelper
{
    public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
    {
        var member = expression.Body as MethodCallExpression;

        if (member != null)
            return member.Method;

        throw new ArgumentException("Expression is not a method", "expression");
    }
}
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

        MethodInfo mi = MethodInfoHelper.GetMethodInfo<Program>(x => x.Test());
        Console.WriteLine(mi.Name);
Run Code Online (Sandbox Code Playgroud)

Test()是Program类中声明的成员函数.

如果您想支持属性getter和setter,请使用MemberExpressionMemberInfo不是.

  • 只需传递null或默认值代替参数. (3认同)

Fre*_*ric 10

让我在这里对手头的问题添加一些解释。我们正在寻找一种GetMethodInfo(SomeMethodSymbol)返回有关给定方法的信息的方法。这并不直截了当,因为方法可能会在 C# 中重载。所以基本上你需要在调用中提供额外的提示,以使编译器(和其他代码分析器,如 Intellisense)理解你在谈论哪种方法。

比如说,我正在寻找有关该Math.Abs方法的信息。然后我必须指定我正在寻找的方法的哪个重载版本:

// int
MethodInfo info1 = ((Func<int, int>)Math.Abs).Method;

// or double ?
MethodInfo info2 = ((Func<double, double>)Math.Abs).Method;
Run Code Online (Sandbox Code Playgroud)

即使只有一个现有的重载,比如Math.Exp方法,我仍然必须提供类型提示,因为该方法将来可能会被重载,然后代码将不再编译。

直接帮手

鉴于上述说明,我们可以提供以下一组辅助方法,以在一定程度上减轻转换每个方法以获取其信息的繁琐任务:

public static class GetMethodInfoUtil
{
    // No cast necessary
    public static MethodInfo GetMethodInfo(Action action) => action.Method;
    public static MethodInfo GetMethodInfo<T>(Action<T> action) => action.Method;
    public static MethodInfo GetMethodInfo<T,U>(Action<T,U> action) => action.Method;
    public static MethodInfo GetMethodInfo<TResult>(Func<TResult> fun) => fun.Method;
    public static MethodInfo GetMethodInfo<T, TResult>(Func<T, TResult> fun) => fun.Method;
    public static MethodInfo GetMethodInfo<T, U, TResult>(Func<T, U, TResult> fun) => fun.Method;

    // Cast necessary
    public static MethodInfo GetMethodInfo(Delegate del) => del.Method;
}
Run Code Online (Sandbox Code Playgroud)

然后你会像这样使用这些助手:

var methodInfos = new[] {

    // Static methods
    GetMethodInfo<int, int>(Math.Abs),
    GetMethodInfo<double, double>(Math.Abs),
    GetMethodInfo<long, long, long>(Math.Max),

    // Static void methods
    GetMethodInfo(Console.Clear),
    GetMethodInfo<string[]>(Main),

    // With explicit cast if too many arguments
    GetMethodInfo((Action<string, object, object>)Console.WriteLine),

    // Instance methods
    GetMethodInfo<string, bool>("".StartsWith),
    GetMethodInfo(new List<int>().Clear),
};
Run Code Online (Sandbox Code Playgroud)

请注意,除了不带参数的 void 静态方法外,仍应提供类型信息Console.Clear。此外,对于实例方法,应该使用实际实例来获取适当的方法,这会使用更多资源。

间接帮手

现在对于某些极端情况,上述助手将不起作用。out例如,假设该方法使用参数。在那些特殊情况下,从 lambda 表达式中提取方法信息变得很方便,我们回到其他海报提供的解决方案(代码灵感来自此处):

public static class GetIndirectMethodInfoUtil
{
    // Get MethodInfo from Lambda expressions
    public static MethodInfo GetIndirectMethodInfo(Expression<Action> expression) 
        => GetIndirectMethodInfo((LambdaExpression)expression);
    public static MethodInfo GetIndirectMethodInfo<T>(Expression<Action<T>> expression) 
        => GetIndirectMethodInfo((LambdaExpression)expression);
    public static MethodInfo GetIndirectMethodInfo<T, TResult>(Expression<Func<TResult>> expression) 
        => GetIndirectMethodInfo((LambdaExpression)expression);
    public static MethodInfo GetIndirectMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression) 
        => GetIndirectMethodInfo((LambdaExpression)expression);

    // Used by the above
    private static MethodInfo GetIndirectMethodInfo(LambdaExpression expression)
    {
        if (!(expression.Body is MethodCallExpression methodCall))
        {
            throw new ArgumentException(
                $"Invalid Expression ({expression.Body}). Expression should consist of a method call only.");
        }
        return methodCall.Method;
    }
}
Run Code Online (Sandbox Code Playgroud)

你会使用这样的:

int dummyInt;
var moreMethodInfos = new[]
{
    // Extracted from lambdas
    GetIndirectMethodInfo(() => "".StartsWith("")),
    GetIndirectMethodInfo((string s) => s.StartsWith(s)),
    GetIndirectMethodInfo(() => int.TryParse("", out dummyInt)),
};
Run Code Online (Sandbox Code Playgroud)

请注意,类型信息仍然是从参数类型间接提供的。还要注意,添加了一个虚拟参数只是为了可以使用out参数。

完整的演示程序:https : //dotnetfiddle.net/CkS075


ole*_*sii 6

考试班

public class  Foo
{
    public void DoFoo()
    {
        Trace.WriteLine("DoFoo");
    }

    public static void DoStaticFoo()
    {
        Trace.WriteLine("DoStaticFoo");
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以做这样的事情

MethodInfo GetMethodInfo(Action a)
{
    return a.Method;
}

var foo = new Foo();
MethodInfo mi = GetMethodInfo(foo.DoFoo);
MethodInfo miStatic = GetMethodInfo(Foo.DoStaticFoo);

//do whatever you need with method info
Run Code Online (Sandbox Code Playgroud)

更新
每@格雷格评论,如果你有一些参数的方法,你可以使用Action<T>,Action<T1, T2>,Action<T1, T2, T3>,或Func<T1>,不便之处是,你仍然需要编写重载GetMethodInfo.


Mat*_*cha 5

我知道这是一个非常古老的帖子,但我会把它扔给那些可能仍在寻找一个简单的解决方案的人.这似乎没有人想到最简单的解决方案:

typeof(Program).GetMethods();
Run Code Online (Sandbox Code Playgroud)

返回一个数组,其中包含Program类中所有方法的MethodInfo,无论属性如何或是否具有参数.

例如,您可以根据需要迭代它,以列出所有10.000+方法的名称.

typeof(Program).GetMethod(nameof(Program.Main));如果方法的名称更改,您也可以这样做Visual Studio的重构也将在此处重命名.

注意:5年前发布问题时,"nameof"关键字无法使用.