c# - 如何将值存储到通用类字段中 (Mono.Cecil)

标签 c# generics il mono.cecil

我正在使用 Mono.Cecil 重写一些程序集。例如,给定一个带有字符串字段的泛型类。我想将代码生成到写入该字段的此类的方法中。 这是实现该目标的代码:

var origInstanceField = type.Fields.First(fld => fld.Name.Equals("_original"));
InsertBeforeReturn(instanceMethod.Body, new[]
{
   Instruction.Create(OpCodes.Ldarg_0),
   Instruction.Create(OpCodes.Ldstr, "genCodeToOriginal"),
   Instruction.Create(OpCodes.Stfld, origInstanceField)
});

对于非泛型类,它就像一个魅力。对于通用类,它会创建糟糕的 IL。如果您查看反编译的 IL,您会发现与编译器发出的相同指令相比的差异。

.method public hidebysig instance void FillFields() cil managed
{
.maxstack 8
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldstr "non-gen code to non-gen field"
L_0007: stfld string TestConsole.GenericClass`1<!T>::_original
L_0017: ldarg.0 
L_0018: ldstr "genCodeToOriginal"
L_001d: stfld string TestConsole.GenericClass`1::_original
L_0022: ret 
}

字段引用指向开放泛型类型 [GenericClass<>] 而不是要构造的类型 [GenericClass< T>]。 我也尝试使用具有相同结果的静态字段。
知道如何获得正确的 FieldDefinition 吗?

最佳答案

我通过查看 Anotar 的源代码 (https://github.com/Fody/Anotar) 设法找到了解决方案。诀窍是创建一个字段引用,其类型定义引用实例化的泛型,而不是原始泛型。

var declaringType = new GenericInstanceType(definition.DeclaringType);
foreach (var parameter in definition.DeclaringType.GenericParameters)
{
     declaringType.GenericArguments.Add(parameter);
}
return new FieldReference(definition.Name, definition.FieldType, declaringType);

在来自类型的 FieldDefinition 上使用此转换可提供正确的 FieldReference。将通用参数提供给通用参数有点奇怪,但很有意义。

关于c# - 如何将值存储到通用类字段中 (Mono.Cecil),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29372777/

相关文章:

c# - 在 C# .NET 1.1 中打印哈希表的键和数据

c# - SQL 2008 : returning data rows as JSON?

Java 泛型转换

c# - 用户操作后从用户控件返回值

c# - 通用存储库包含和过滤

Java 集合通配符

c# - 高性能克隆

c# - 以编程方式修改元数据(.net 可执行文件)

c# - 如何为 ulong.Parse 调用发出 LDC_I8?

c# - 使用 tripleDES 加密和解密文件