从 Mono.Cecil 中的引用获取成员定义

Get member definition from reference in Mono.Cecil

我注意到某些类型的方法(例如泛型方法)中的字段或方法引用将是 FieldReference 类型,而不是 FieldDefinition,尽管字段(或方法)在同一模块中,在同一类型中。我怎样才能从这个FieldReference得到FieldDefinition

我尝试了 module.Importmodule.MetadataResolver.Resolve,但都不起作用。

跟进 this 问题,但更笼统。

编辑:

一个简单的通用类:

public class HelperClass<T>
{
    private int _someInt;

    void SomeMethod(int i)
    {
        _someInt = i;
    }
}

SomeMethod 的正文包含:

...
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: stfdl System.Int32 HelperClass`1<T>::_someInt
....

IL_000a 操作码的操作数通常应该是 FieldDefinition,毕竟它在同一个模块中。但是因为我想 HelperClass 是通用的,操作数是一个无法解析的 FieldReference,我只能希望比较全名以实际找到 FieldDefinition

在这种情况下,这不是什么大问题,但是当引用是对其他泛型类型中的其他成员时,我相信有比枚举所有类型来查找更好的方法定义。

编辑:

HelperClass<> 来自 AssemblyDefinition.ReadAssembly 在运行时加载的模块,即 .Resolve() returns null 而不是返回 FieldDefinition .

更新:

事实证明,因为我正在更改通用类型中的字段名称,所以引用中断并且 Resolve() 返回 null。仍在为 this one.

寻找合适的解决方案

更新:

我更改了代码以将类型分离到不同解决方案中的不同项目中。不幸的是,我仍然无法重现该问题,但如果有帮助,我愿意继续尝试。

我可以使用以下代码解析类型引用。如果你能提供更多的复制细节,我愿意再试一次:-)

这是名为 TargetLibrary.dll 的程序集中的唯一类型。我在自己的解决方案中编译它,并将程序集复制到 C:\Temp.

public class HelperClass<T>
{
    private int _someInt;

    void SomeMethod(int i)
    {
        _someInt = i;
    }
}

此代码位于不同的程序集中,在其自己的解决方案中被编译成控制台 exe 文件。

class Program
{
    static void Main(string[] args)
    {
        var module = AssemblyDefinition.ReadAssembly(@"C:\Temp\TargetLibrary.dll").MainModule;

        Console.WriteLine("For HelperClass<>");
        var helperClass = module.Types[1];
        var someMethod = helperClass.Methods[0];
        var someMethodBody = someMethod.Body;
        foreach (var instruction in someMethodBody.Instructions)
        {
            Console.WriteLine(
                "{0}\t{1}\t{2}",
                instruction.Offset,
                instruction.OpCode.Code,
                instruction.Operand == null ? "<null>" : string.Format("{0} / {1}", instruction.Operand.GetType().FullName, instruction.Operand.ToString()));

            var fieldReference = instruction.Operand as FieldReference;
            if (fieldReference != null)
            {
                var fieldDefinition = fieldReference.Resolve();
                Console.WriteLine(
                    "\t\tResolved field reference operand: {0} / {1}",
                    fieldDefinition.GetType().FullName,
                    fieldDefinition.ToString());
            }
        }
    }
}

运行 这会产生以下输出。

For HelperClass<>
0       Ldarg_0 <null>
1       Ldarg_1 <null>
2       Stfld   Mono.Cecil.FieldReference / System.Int32 TargetLibrary.HelperClass`1<T>::_someInt
                Resolved field reference operand: Mono.Cecil.FieldDefinition / System.Int32 TargetLibrary.HelperClass`1::_someInt
7       Ret     <null>