通过反射找到特定的方法

时间:2020-01-30 14:22:31

标签: c# reflection

假设我们在一个类中有两个公共方法:

public class SomeClass
{
    public bool DoSomething(int param1)
    {
        return param1 == 30;
    }

    public bool DoSomethingElse(int param1)
    {
        param1 *= 2;
        return param1 == 30;
    }
}

我可以编写以下代码来使用反射来获取这两种方法:

MethodInfo[] methods = typeof(SomeClass).GetMethods(BindingFlags.Public | BindingFlags.Instance)
                       .Where(x => x.ReturnType == typeof(bool)
                              && x.GetParameters().Length == 1
                              && x.GetParameters()[0].ParameterType == typeof(int)).ToArray();

假设我只想要DoSomethingElse,我可以只使用methods[1]

但是,假设他们在下次编译此类时交换了位置。我将以DoSomething结尾。

将这两种方法分开的唯一方法是,DoSomethingElse在检查之前将参数乘以2。

我还能用反射做其他检查以确保我总是得到DoSomethingElse吗?

注意:每次查找时,我正在寻找的方法的名称可能都会更改,因此简单地搜索它们的名称也不起作用。

1 个答案:

答案 0 :(得分:3)

从技术上讲,您可以分析方法的 IL代码;让我们检查一下前* 2个IL代码中是否有10

https://en.wikipedia.org/wiki/List_of_CIL_instructions

代码:

  MethodInfo[] methods = GetType()
    .GetMethods(BindingFlags.Public | BindingFlags.Instance)
    .Where(x => x.ReturnType == typeof(bool)
           && x.GetParameters().Length == 1
           && x.GetParameters()[0].ParameterType == typeof(int))
    .Where(m => m
       .GetMethodBody()
       .GetILAsByteArray()
       .Take(10)                  // take first 10 IL codes
       .SkipWhile(b => b != 0x18) // ldc.i4.2 : load 2
       .Any(b => b == 0x5A))      // mul      : multiply 
    .ToArray();

让我们看看:

  Console.Write(string.Join(Environment.NewLine, methods.Select(m => m.Name)));

结果:

  DoSomethingElse

但是,我强烈建议您使用特定方法Name或使用属性等标记方法。