如何获取方法中引用的所有属性?

时间:2016-05-03 17:08:08

标签: c# .net mono.cecil

假设我们有一些人最终会消费:

public class SampleClass
{
    [Obsolete("This property was slain in Moria", false)]
    public double SampleProperty { get; set; }

    [Obsolete("This method was slain in Moria", false)]
    public static void SampleMethod()
    {
    }
}

然后让我们说有人消费它:

public static double SampleConsumer()
{
    SampleClass.SampleMethod();
    var classy = new SampleClass();
    return classy.SampleProperty;
}

我正在尝试确定SampleConsumer中对过时方法和属性的所有引用。

我已经想出了如何获取这些方法,感谢Kris's response to this question.总之,这看起来像:

public static void GetMethodReferences(MethodDefinition method)
{
    foreach (var instruction in method.Body.Instructions)
    {
        if (instruction.OpCode == OpCodes.Call)
        {
            MethodReference methodCall = instruction.Operand as MethodReference;  
            // ...

其中methodCall.CustomAttributes将包含我们希望检测的过时属性。

我正在尝试为属性引用完成类似的事情。

到目前为止我尝试过:

请注意,在CIL中,classy.SamplePropertycallvirt指令表示:

System.Double FoobarNamespace.SampleClass::get_SampleProperty()

我尝试在OpCodes.Callvirt中包含GetMethodReferences,但虚拟get方法似乎唯一的属性是CompilerGeneratedAttribute(没有过时的属性)。

接下来,我决定查看虚拟get方法。迭代虚拟方法的说明,请注意有ldfld l oa d f ,即 ld )说明:

System.Double FoobarNamespace.SampleClass::<SampleProperty>k__BackingField    

我尝试检查它是否有过时的属性:

// for each instruction in the virtual get_SampeProperty()  
    if (instruction.OpCode == OpCodes.Ldfld)
    {
        var fieldDefinition = instruction.Operand as MethodDefinition;
        // check fieldDefinition.Attributes   
        // check fieldDefinition.CustomAttributes   
        // but neither of them have the Obsolete attribute  
        // ...

我认为我实际需要做的是为PropertyDefinition获取PropertyReferenceSampleProperty,但我似乎无法弄清楚如何在{消费者方法。

想法?

1 个答案:

答案 0 :(得分:0)

在IL中,没有方法的属性概念,只有属性的方法概念。我认为塞西尔反映了这一点,所以你不能从MethodDefinitionPropertyDefinition,但你可以反过来做。

代码看起来像(未经测试):

MethodDefinition method;

PropertyDefinition property = method.DeclaringType.Properties
    .SingleOrDefault(p => p.GetMethod == method || p.SetMethod == method);

请记住,理论上单个方法可能属于多个属性,但我认为任何理智的编译器都不会这样做。