ヘジ・オール
新しい TYPE ランタイムを構築するコードがいくつかあります。それは MethodBuilder を使用して GET および SET メソッドを設定します。(これはウェブからの例であり、それを書いたガイのおかげで、残念ながら彼への参照を失いましたが、彼は私の考えの中にあります)
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 をより複雑なものに変更したいので、このテスト コードを記述します。
public class Customer { プライベート文字列 _name; パブリック文字列名 { get { return _name; } set { if ( string.IsNullOrEmpty( value ) ) { throw new ValidationException("値を設定してください"); } _name = 値; } } パブリック文字列の姓 { 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 コードに実装することです。
// 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);
これは、私が不足しているところです、私はそれを働かせることができません。コードを「ただ」コピーすることはできず、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行目で、これらの赤い下線はエラーを示しています...
- Bool = ") 期待される"
- [mscorlib]システム = "; 期待"
- :: = "。期待"
- そして最後の ) は「無効な式用語文字列」を与える
リフレクターを使用できないのはなぜでしょうか。コードは問題ないはずですか? また?
EMITステートメントで使用できるMSILコードを表示するプログラム/メソッドを見つけることが解決策です。
これは単なる例であるため、コードは変更されるため、正しいコードに回答するための解決策ではありません (例を機能させることは素晴らしいことです) が、C# から正しい MSIL を取得するためのより恒久的な "方法" です。
Peww、長い質問です。ここにすべてが揃っていることを願っています。
よろしくリロード