gpt4 book ai didi

c# - Silverlight 3.0 C# - 使用 Methodbuilder 创建 SET 方法,并使用 ILGenerator 和 Emit 添加 MSIL

转载 作者:行者123 更新时间:2023-11-30 22:47:52 26 4
gpt4 key购买 nike

一切皆有可能

我有一些构建新 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)类客户 { 私有(private)字符串_name; 公共(public)字符串名称 { 得到 { 返回 _name; } 放 { 如果 (字符串.IsNullOrEmpty(值)) { throw new ValidationException("请设置一个值"); } _name = 值; } } 公共(public)字符串姓氏 { 得到;放; }

编译然后使用 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]System = "; expected"
  • ::= ".预期"
  • 最后一个 ) 给出“无效表达词串”

我想知道为什么我不能使用反射器,代码应该没问题?或者?

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

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

Peww,一个很长的问题,我希望我能在这里找到所有内容。

问候重新加载

最佳答案

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

您需要获取 MethodInfo - 在本例中:

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

不过,实际上,我会为此研究Expression - 我相信有一个Compile for silverlight Expression ,而且您不必学习 IL!

请注意,如果有多个重载,您通常需要做更多的工作才能获得 MethodInfo(恰好 string.IsNullOrEmpty 易于使用) .另外,请注意“实例”方法应使用 OpCodes.Callvirt;静态方法(像这个)应该使用 OpCodes.Call

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

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com