[英]Copy / Reflection.Emit'ting static arrays
我正在嘗試將靜態初始化程序從一個DLL復制到另一個DLL。
如果您在C#中有一個靜態數組初始值設定項,則會得到以下信息:
.class private auto ansi <PrivateImplementationDetails>{0D3E8B0E-F218-435F-989D-9D04F550A786}
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.field assembly static valuetype <PrivateImplementationDetails>{0D3E8B0E-F218-435F-989D-9D04F550A786}/__StaticArrayInitTypeSize=120 $$method0x6000060-1 = ((binary data))
我找到了讀取此數據以使用此方法的最簡單方法:
int size = field.FieldType.StructLayoutAttribute.Size;
byte[] data = new byte[size];
RuntimeHelpers.InitializeArray(data, field.FieldHandle);
基本上,這將為您提供上述的“二進制數據”。
問題1 : Dictionary
會發生什么? 這仍然有效嗎? 我在弄清楚這里到底發生什么時遇到了麻煩(它似乎在反編譯中是隱藏的)...
我已經發現在實現細節中使用的GUID是ModuleBuilder
的版本ID。 使用其他顯式字段信息意味着您應該能夠復制數據。
問題2:你怎么能寫回的數據在另一個ModuleBuilder
/ FieldBuilder
使用Reflection.Emit的?
-
版? .NET 4.5(VS2013默認)
似乎對彈出的Dictionary
感到困惑。 我在代碼中做了一些挖掘,它們似乎以[string-> int]字典的形式彈出,用於解析switch / case語句。
例如,請參見mscorlib.dll v4.0.30319.18444中可以找到它們。 在Reflector中,它們如下所示:
.field assembly static class System.Collections.Generic.Dictionary`2<string, int32> $$method0x6003a20-1
至於原因:在對它們執行一些測試之前,我正在更改DLL。 具有諷刺意味的是,我想要這樣做的原因是因為我不想弄亂實現細節:-),並且因為多個實例可能會帶來麻煩。
換句話說,我基本上只想復制所有它們,就像它們是二進制blob一樣,如果它們具有這樣的奇特數據,而不管類型如何,同時保留名稱。 由於在不同的DLL中以相同的方式對待IL和數據,因此無論編譯器恕我直言,這應該總是可能的,對嗎?
經過數小時的擺弄,這似乎是它的工作方式:
...對於<PrivateImplementationDetails>
每個字段:
可以通過RuntimeHelpers
調用從值類型( field.FieldType.IsValueType
)中獲取數據:
int size = GetManagedSize(field.FieldType);
byte[] data = new byte[size];
RuntimeHelpers.InitializeArray(data, field.FieldHandle);
FieldBuilder mappedField = myType.DefineInitializedData(
field.Name, data, field.Attributes);
有:
public static int GetManagedSize(Type type)
{
var method = new DynamicMethod("GetManagedSizeImpl", typeof(uint), new Type[0],
GetType().Assembly, false);
ILGenerator gen = method.GetILGenerator();
gen.Emit(OpCodes.Sizeof, type);
gen.Emit(OpCodes.Ret);
var func = (Func<uint>)method.CreateDelegate(typeof(Func<uint>));
return checked((int)func());
}
如果是引用類型,則無需執行任何操作,因為使用它們時,它們會初始化為易失性靜態變量。
之后,您需要確保使用生成的fieldinfo代替原始字段。 它們將包含相同的數據。 至於引用,它們被初始化為null
。
顯然,您不想弄亂實現細節本身或使用它們的方式...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.