我想在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>
当我尝试执行修改后的程序集时,我从程序集'TestApp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'得到一个TypeLoadException并显示消息“Type'<Module>
'有一个字段非法的。“
如果我删除FieldAttributes.HasFieldRVA
,我没有错误,但at I_00000000
消失,我认为这意味着该字段不会被初始化。
答案 0 :(得分: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);
答案 1 :(得分:-1)
您可以为<Module>
类创建一个构造函数(静态),并在其中指定值。每当调用类时,将首先初始化构造函数,为您提供值。我个人不确定如何设置初始值,但你可以摆弄一些CIL,或者只是使用导入器将字节从另一个程序集导入到你自己的。
您可以在另一个问题中找到相关示例:Inject Method with Mono.Cecil