Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从方法引用C获取methodinfo#_C#_.net_Reflection_Typeof_Methodinfo - Fatal编程技术网

C# 从方法引用C获取methodinfo#

C# 从方法引用C获取methodinfo#,c#,.net,reflection,typeof,methodinfo,C#,.net,Reflection,Typeof,Methodinfo,当我们想要获取指定类型的类型实例时,可以使用C#typeof关键字。但是,如果我想通过方法的引用获取方法的MethodInfo,我可以使用什么呢 例如,我有一个简单的控制台应用程序。它包含程序.Main方法。我想通过使用类似于methodinfoof(Program.Main)的东西来获取MethodInfo。我有这个问题,因为方法名可能会更改,所以我不能仅使用Type.GetMethodInfo(string-MethodName)来解决这个问题 我有大约10000个方法,我想获得Method

当我们想要获取指定类型的类型实例时,可以使用C#
typeof
关键字。但是,如果我想通过方法的引用获取方法的
MethodInfo
,我可以使用什么呢

例如,我有一个简单的控制台应用程序。它包含
程序.Main
方法。我想通过使用类似于
methodinfoof(Program.Main)
的东西来获取
MethodInfo
。我有这个问题,因为方法名可能会更改,所以我不能仅使用
Type.GetMethodInfo(string-MethodName)
来解决这个问题


我有大约10000个方法,我想获得
MethodInfo
,因此向我的方法添加任何自定义属性或任何其他内容都不是一个解决方案。

对先前发布的答案稍加修改,但这篇博文似乎达到了您的要求

示例用法如下:

var methodInfo = SymbolExtensions.GetMethodInfo(() => Program.Main());
最初的答案是这个问题

测试类

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

    public static void DoStaticFoo()
    {
        Trace.WriteLine("DoStaticFoo");
    }
}
你可以这样做

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
更新

根据@Greg注释,如果您对方法有一些参数,您可以使用
Action
Action
Action
、或
Func
,不便之处在于您仍然需要为
GetMethodInfo

编写重载。您可以对非静态方法使用表达式树。这里有一个例子

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");
    }
}
使用System.Linq.Expressions;
运用系统反思;
公共静态类MethodInfoHelper
{
公共静态MethodInfo GetMethodInfo(表达式)
{
var member=expression.Body作为MethodCallExpression;
如果(成员!=null)
返回成员。方法;
抛出新ArgumentException(“表达式不是方法”、“表达式”);
}
}
您可以这样使用它:

        MethodInfo mi = MethodInfoHelper.GetMethodInfo<Program>(x => x.Test());
        Console.WriteLine(mi.Name);
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),
};
int dummyInt;
var moreMethodInfos = new[]
{
    // Extracted from lambdas
    GetIndirectMethodInfo(() => "".StartsWith("")),
    GetIndirectMethodInfo((string s) => s.StartsWith(s)),
    GetIndirectMethodInfo(() => int.TryParse("", out dummyInt)),
};
MethodInfo mi=MethodInfoHelper.GetMethodInfo(x=>x.Test());
Console.WriteLine(mi.Name);
Test()是程序类中声明的成员函数


如果您想支持属性getter和setter,请改用
MemberExpression
MemberInfo

我创建了一个T4模板,该模板创建了所需的帮助函数来帮助您实现这一点。它创建一个函数列表,以从Func或Action方法获取MethodInfo对象

将以下代码复制到名为
GetMethodInfo.tt
的文件中:

<#@ template language="C#" #>
<#@ output extension=".cs" encoding="utf-8" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
using System;
using System.Linq.Expressions;
using System.Reflection;

namespace Tools
{
    public static class GetMethodInfo
    {
<# int max = 12;
for(int i = 0; i <= max; i++) 
{
    var builder = new StringBuilder();

    for(int j = 0; j <= i; j++) 
    {
        builder.Append("T");
        builder.Append(j);
        if(j != i) 
        {
            builder.Append(", ");
        }
    }

    var T = builder.ToString();
#>
        public static MethodInfo ForFunc<T, <#= T #>>(Expression<Func<T, <#= T #>>> expression)
        {
            var member = expression.Body as MethodCallExpression;

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

            throw new ArgumentException("Expression is not a method", "expression");
        }

        public static MethodInfo ForAction<<#= 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");
        }

<# } #>
    }
}

使用制度;
使用System.Linq.Expressions;
运用系统反思;
名称空间工具
{
公共静态类GetMethodInfo
{

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

typeof(Program).GetMethods();
返回一个数组,其中包含程序类中所有方法的MethodInfo,而不考虑属性或是否具有参数

例如,如果希望列出所有10.000+方法的名称,可以对其进行迭代

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

注意:5年前发布问题时,“nameof”关键字不可用。

可能不是理想的方式,但它可以帮助:

不使用lambdas/表达式的解决方案:

var callback = typeof(BlogController).GetMethod(nameof(BlogController.GetBlogs));

让我在这里为这个问题添加一些解释。我们正在寻找一个方法
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;
然后,您将使用以下帮助程序:

        MethodInfo mi = MethodInfoHelper.GetMethodInfo<Program>(x => x.Test());
        Console.WriteLine(mi.Name);
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),
};
int dummyInt;
var moreMethodInfos = new[]
{
    // Extracted from lambdas
    GetIndirectMethodInfo(() => "".StartsWith("")),
    GetIndirectMethodInfo((string s) => s.StartsWith(s)),
    GetIndirectMethodInfo(() => int.TryParse("", out dummyInt)),
};
您可以使用以下内容:

        MethodInfo mi = MethodInfoHelper.GetMethodInfo<Program>(x => x.Test());
        Console.WriteLine(mi.Name);
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),
};
int dummyInt;
var moreMethodInfos = new[]
{
    // Extracted from lambdas
    GetIndirectMethodInfo(() => "".StartsWith("")),
    GetIndirectMethodInfo((string s) => s.StartsWith(s)),
    GetIndirectMethodInfo(() => int.TryParse("", out dummyInt)),
};
请注意,类型信息仍然是从参数类型间接提供的。还请注意,添加了一个伪参数只是为了能够使用
out
参数


完整的演示程序:。

查看我针对上一个问题发布的答案;这可能有助于您实现目标。@ChrisMcAtackney您可能希望将此作为答案发布,该链接有一个可行的解决方案。另请参阅Eric Lippert的“In Foof We Trust:对话”至少,我对这个用例很好奇。可能重复的只是传递null或默认值来代替参数。有什么方法可以让这个在静态类中的静态方法上工作吗?@Jason-你可以让它与任意数量的参数一起工作。而不是使用
Action
Action
Action
Action
Action在
Func
上,@Jason它确实适用于
程序。Main
,请参阅静态版本的更新。如果方法不是
操作,它也可以工作,因为您可以看到该方法返回void。但是为了使用这种构造,该方法应作为
操作
传入。这回答了OP中如何获取方法info@Jason没错,我明白了,你担心的是
参数
,而不是
静态
@Jason-在这种情况下使用。我认为oleksii的答案看起来更干净,但Dmitry的更灵活。但实际上,大多数方法都可以被十几个重载覆盖,并且可以根据需要添加额外的重载。@Jason:它有一个覆盖层oad没有参数。@Jason:你把我弄丢了-你的观点是什么?上面发布的代码确实有效,并且给出了原始问题所要求的内容。Program.Main的MethodInfo。如果你想要有字符串[]参数的重载的MethodInfo,那么就这样调用它;SymbolExtensions.GetMethodInfo(()=>Program.Main(null);请注意,这种方法有其局限性(请参阅)。其次,最好检查一下