获取存储在二进制字段签名中的类型

时间:2014-11-29 19:19:43

标签: c# .net reflection clr cil

假设您在.NET模块中有一个字段签名的二进制表示,如0604。 6(FIELD)表示字段调用约定,4(ELEMENT_TYPE_I1)表示I1基元类型(有关CIL的更多信息,请参阅ECMA-335)。签名可以来自调试器或装配检查器,这并不重要。更重要的是,是否有可能(使用.NET提供的方法)解析"这个签名并获得签名所代表的相应.NET类型?

示例:

0601System.Void
0604System.SByte
060ESystem.String
061408020000System.Int32[,]

2 个答案:

答案 0 :(得分:1)

我不知道任何可以执行此操作的公共API,但Cecil可以在内部解析此类签名,因此您可以复制其代码。

相关代码位于SignatureReader.ReadTypeSignature()

或者也许不要自己尝试解析程序集并使用Cecil。

答案 1 :(得分:0)

有一些内部.NET方法可以做到这一点:

public static unsafe Type GetTypeFromFieldSignature(byte[] signature, Type declaringType = null)
{
    declaringType = declaringType ?? typeof(object);
    Type sigtype = typeof(Type).Module.GetType("System.Signature");
    Type rtype = typeof(Type).Module.GetType("System.RuntimeType");
    var ctor = sigtype.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new[]{typeof(void*), typeof(int), rtype}, null);
    fixed(byte* ptr = signature)
    {
        object sigobj = ctor.Invoke(new object[]{(IntPtr)ptr, signature.Length, declaringType});
        return (Type)sigtype.InvokeMember("FieldType", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, sigobj, null);
    }
}

这会加载任何有效的字段签名并返回相应的类型。