Hej All

我有一些代码可以构建新的TYPE运行时,它使用MethodBuilder设置GET和SET方法。 (这是网上的一个例子,这要归功于盖伊(Guy)编写的,我很遗憾失去了对他的推荐,但他在我的脑海中

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更改为更复杂的方法,因此我编写了此测试代码。

公共类客户
    {
        私人字串_name;
        公共字符串名称
        {
        得到{return _name; }
        设置{
                如果(string.IsNullOrEmpty(value))
                {
                    抛出新的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行,这些红色下划线给出了错误。


布尔=“)表示感谢”
[mscorlib] System =“;预期”
:: =“。预期”
最后一个)给出“无效
表达式术语字符串”


我不知道为什么我不能使用反射器,代码应该可以吗?要么?

它的解决方案是找到一个程序/方法,以显示可在EMIT语句中使用的MSIL代码。

这只是一个示例,因此代码会发生变化,因此它不是解决正确代码的解决方案(尽管使示例正常工作会很好),而是从C#获取正确MSIL的更持久的“方式”。

皮尤,一个漫长的问题,我希望我在这里有一切。

问候
重新载入

最佳答案

currSetIL.Emit(OpCodes.Call bool [mscorlib] System.String :: IsNullOrEmpty(string); //调用bool [mscorlib] System.String :: IsNullOrEmpty(string)


您需要获取MethodInfo-在这种情况下:

currSetIL.EmitCall(OpCodes.Call,typeof(string).GetMethod("IsNullOrEmpty"),null);


但是,实际上,我正在为此调查Expression-我相信Silverlight Compile有一个Expression,而且您不必学习IL!

请注意,如果存在多个重载,则通常必须做更多的工作才能获得MethodInfostring.IsNullOrEmpty易于使用)。另外,请注意,“实例”方法应使用OpCodes.Callvirt;静态方法(如此类)应使用OpCodes.Call

关于c# - Silverlight 3.0 C#-使用Methodbuilder创建SET方法,并使用ILGenerator和Emit添加MSIL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2071512/

10-11 21:59
查看更多