C# &引用;未能解析T[]modreq(System.Runtime.CompilerServices.IsVolatile)";
用户报告了以下错误消息:C# &引用;未能解析T[]modreq(System.Runtime.CompilerServices.IsVolatile)";,c#,cil,mono.cecil,C#,Cil,Mono.cecil,用户报告了以下错误消息: 无法解析T[]modreq(System.Runtime.CompilerServices.IsVolatile) 这是有问题的代码行: public static TypeDefinition ResolveTypeReference(this TypeReference typeReference) { return typeReference.Resolve() ?? throw new ResolutionException(typeReference)
无法解析T[]modreq(System.Runtime.CompilerServices.IsVolatile)
这是有问题的代码行:
public static TypeDefinition ResolveTypeReference(this TypeReference typeReference)
{
return typeReference.Resolve() ?? throw new ResolutionException(typeReference);
}
此方法在操作码为操作码.Ldfld
或操作码.Ldobj
的指令的操作数上调用
ResolutionException
是MonoCecil
库中的一个类:
public ResolutionException(MemberReference member)
: base("Failed to resolve " + member.FullName)
{
if (member == null)
throw new ArgumentNullException(nameof (member));
this.member = member;
}
也就是说,有问题的TypeReference
的FullName
属性的值是T[]modreq(System.Runtime.CompilerServices.IsVolatile)
不幸的是,我没有更多的堆栈跟踪可供共享,因此请原谅我的模糊问题:
TypeReference
的FullName
属性设置为T[]modreq(System.Runtime.CompilerServices.IsVolatile)
全名的相同原因,还是由于其他原因
公共C类
{
公共挥发性T[]字段;
公屋
{
var-temp=字段;
}
}
兴趣的指导是
IL_0004: ldfld !0[] modreq([System.Private.CoreLib]System.Runtime.CompilerServices.IsVolatile) class C`1<!T>::'field'
IL_0004:ldfld!0[]modreq([System.Private.CoreLib]System.Runtime.CompilerServices.IsVolatile)类C`1::'field'
!0[]
用于表示泛型数组,而不是T[]
。这激发了我的第一个问题。我最终解决了这个问题,检查我正在解析的类型是否是RequiredModifierType,然后再解析它的元素类型(如果是该类型)
if (tr is RequiredModifierType)
tr = tr.GetElementType();
var td = tr.Resolve();
没有太多(任何?)文档,但Cecil似乎将volatile修饰符作为一种封闭类型进行了表面处理。据我所知,解决这个问题总是失败的。看起来像是Cecil的一个缺陷/限制。
modreq
表示字段
是volatile
,需要将其传递给方法,以确保JIT只生成volatile.
前缀访问。这是正确的,Cecil认为它是类型名称的一部分是不正确的(但如果您生成访问操作码,那么它是类型的一部分可以被认为是“正确的”,所以是的)。准确地说,字段的类型实际上是T[]modreq(IsVolatile)
,由于modreq
修饰符是该类型的一部分,但是尝试将其用作完整的类型名是不正确的/将失败,因为它是基于T[]
的类型,其中T
是该类的第一个泛型参数(这就是!0
的意思;在IL级别上,类型参数除了用于漂亮打印之外没有其他名称)。在“正常”反射中,这不是通过类型
而是通过字段信息。GetRequiredCustomModifiers()公开的
@jeroenmoster感谢您的回复。出于好奇,我试图用一个包含public volatile int[]的类来重现这个错误字段
,但我无法。键入解析成功,并且未引发任何
ResolutionException。根据您的解释,我本以为会遇到相同的错误。我是否误解了什么?不,这只是表明,显然是错误(如果它是一个bug,可能只是一个API限制或误用,我无法真正判断,因为我对Cecil几乎没有经验)被限制为泛型类型(甚至可能是泛型类型的数组)。解析逻辑显然不会在modreq(Volatile)上出错
一般来说。您应该看看ResolveTypeReference
是如何被调用的——我可以很容易地想象,试图将一个开放泛型类型(C
)字段的“类型”解析为这种方式失败。
if (tr is RequiredModifierType)
tr = tr.GetElementType();
var td = tr.Resolve();