HEJ所有的Silverlight 3.0 C# - 使用Methodbuilder創建一組方法,並添加具有的ILGenerator的MSIL,併發出
我有一些代碼,建立一個新的類型的運行時,它設置使用MethodBuilder GET和SET方法。 (其從網站的exampel,並感謝傢伙,那寫的,我unfortantly失去了參考文獻給他,但他是我的想法)
TypeBuilder typeBuilder = module.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class);
我添加一個方法到類這樣。
MethodAttributes GetSetAttr =
MethodAttributes.Public |
MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr =
typeBuilder.DefineMethod("get_value",
GetSetAttr,
typeof(string),
Type.EmptyTypes);
// Intermediate Language stuff...
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for current private field.
MethodBuilder currSetPropMthdBldr =
typeBuilder.DefineMethod("set_value",
GetSetAttr,
null,
new Type[] { typeof(string) });
// Again some Intermediate Language stuff...
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
它工作正常,我卻想對使用setMethod更改爲更復雜的東西,所以我寫這篇文章的測試代碼。
公共類客戶 {0}私人字符串_名稱; 公共字符串名稱 { get {return _name; } set if(string.IsNullOrEmpty(value)) {0} {0} {0}拋出new ValidationException(「請設置一個值」); } _name = value; } } public string lastname {get;組; } }
編譯然後使用Reflector來獲取MSIL。
.method public hidebysig specialname instance void set_name(string 'value') cil managed
{
.maxstack 2
.locals init (
[0] bool CS$4$0000)
L_0000: nop
L_0001: ldarg.1
L_0002: call bool [mscorlib]System.String::IsNullOrEmpty(string)
L_0007: ldc.i4.0
L_0008: ceq
L_000a: stloc.0
L_000b: ldloc.0
L_000c: brtrue.s L_001a
L_000e: nop
L_000f: ldstr "Please set a value"
L_0014: newobj instance void [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationException::.ctor(string)
L_0019: throw
L_001a: ldarg.0
L_001b: ldarg.1
L_001c: stfld string AnnotationTest.MainPage/Customer::_name
L_0021: ret
}
因此,任務是將它實現到SET EMIT代碼中。
currSetIL.Emit(OpCodes.Ldarg_0); currSetIL.Emit(OpCodes.Ldarg_1); currSetIL.Emit(OpCodes.Stfld, field); currSetIL.Emit(OpCodes.Ret);
這就是我來的短,我不能讓它的工作。它接縫,我可以「只是」複製代碼,而我的MSIL技能是有限的。以下是我的錯誤。
currSetIL.Emit(OpCodes.Nop); // L_0000: nop
currSetIL.Emit(OpCodes.Ldarg_1); // L_0001: ldarg.1
currSetIL.Emit(OpCodes.Call bool [mscorlib]System.String::IsNullOrEmpty(string);// call bool [mscorlib]System.String::IsNullOrEmpty(string)
在第3行中,這些紅色下劃線給thede錯誤...
- 布爾= 「)Expetced」
- [mscorlib程序]系統= 「預期的」
- :: = 「預期」
- 和最後一個)給出 「無效 表達術語串」
我想知道爲什麼我不能使用反射器,代碼應該沒問題?要麼?
找到一個程序的方法/顯示可以在EMIT語句中使用的MSIL代碼的方法。
這只是一個例子,所以代碼將會改變,所以它不是一個解決方案來回答正確的代碼(所有的代碼都可以正常工作),而是一個更爲透徹的方式來獲得正確的MSIL C#。
Peww,一個很長的問題,我希望我在這裏擁有一切。
問候 的重新裝載
重新評論; AFAIK這將是一個相當手動的翻譯。不過,嚴肅地說,我認爲你可以通過'Expression'來完成所有這些工作(特別是在新對象的情況下)。你有沒有想要達到的例子?即你可以發佈C#等價於你想要的東西嗎? – 2010-01-15 16:32:55