1

我想向类添加一个类型的字段,byte[]<Module>使用 Mono.Cecil 将其初始化为任意字节数组。以下不起作用。

TypeDefinition moduleClass = ModuleDefinition
    .GetAllTypes()
    .Single(typedef => typedef.Name == "<Module>");

FieldDefinition myBytes = new FieldDefinition("myBytes"
    ,FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.HasFieldRVA
    ,ModuleDefinition.Import(typeof(byte[])));

myBytes.InitialValue = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

moduleClass.Fields.Add(myBytes);

这是 ILSpy 中的结果(使用“IL”视图)。

.class private auto ansi '<Module>'
{
    // Fields
    .field private static uint8[] myBytes at I_00000000

} // end of class <Module>

当我尝试执行修改后的程序集时,我得到一个 TypeLoadException 消息“类型' <Module>'来自程序集'TestApp,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null'有一个非法类型的字段。”

如果我删除FieldAttributes.HasFieldRVA,我不会收到任何错误,但会at I_00000000消失,我认为这意味着该字段不会被初始化。

4

2 回答 2

1

初始化一个原始值,就像你想初始化完美byte的作品一样。filed.InitialValue我不知道为什么它在这里不起作用。也许 Jb Evain 可以说出来。

请注意,如果您定义 s 静态字段并设置初始值,则发生的情况是您设置了 RVA,然后在静态构造函数中,该字段将使用此 RVA toekn 中存在的数据进行初始化。

因此,为了解决这个问题,我建议您在静态构造函数中自己初始化字段,而不使用 RVA。在我的例子中,我初始化了一个 2 字节的字节数组。

var staticConstructorAttributes = 
    Mono.Cecil.MethodAttributes.Private|
    Mono.Cecil.MethodAttributes.HideBySig |
    Mono.Cecil.MethodAttributes.SpecialName |
    Mono.Cecil.MethodAttributes.RTSpecialName |
    Mono.Cecil.MethodAttributes.Static;

MethodDefinition staticConstructor = new MethodDefinition(".cctor", staticConstructorAttributes, module.TypeSystem.Void);
type.Methods.Add(staticConstructor);
type.IsBeforeFieldInit = false;
var il = staticConstructor.Body.GetILProcessor();

il.Emit(OpCodes.Ldc_I4_2); // if your array size is bigger than 4 you need to emit Ldc_I4_S or Ldc_I4
il.Emit(OpCodes.Newarr, module.TypesSystem.Byte); //create a new byte array
il.Emit(OpCodes.Stsfld, myBytesField); //store it in the myBytes static field
il.Emit(OpCodes.Ldsfld, myBytesField); // load the field
il.Emit(OpCodes.Ldc_I4_0); // index
il.Emit(OpCodes.Ldc_I4_0); // value
il.Emit(OpCodes.Stelem_I1); // store the byte value in the given index
il.Emit(OpCodes.Ldsfld, myBytesField);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Stelem_I1);
il.Emit(OpCodes.Ret);
于 2016-11-29T09:27:21.967 回答
-1

您可以为<Module>该类创建一个构造函数(静态)并在其中分配值。每当调用该类时,都会首先初始化构造函数,为您提供值。我个人不确定如何设置初始值,但您可以摆弄一些 CIL 或简单地使用导入器将字节从另一个程序集导入到您自己的程序集中。

您可以在另一个问题中找到这样的示例:Inject Method with Mono.Cecil

于 2014-05-06T06:48:19.077 回答