EmitCall 引发“操作可能会破坏运行时的稳定性”在银光中
我的 IL 语言是 n00b。在我的任务中,我必须创建从 System.ServiceModel.DomainServices.Client.Entity 继承的动态类型。当我添加额外的代码来设置属性方法时,我收到“操作可能会破坏运行时的稳定性”。请帮我解决这个问题。
来自 Reflector 的代码:
L_0000: nop
L_0001: ldarg.0
L_0002: ldstr "Field"
L_0007: ldarg.1
L_0008: call instance void [System.ServiceModel.DomainServices.Client]System.ServiceModel.DomainServices.Client.Entity::ValidateProperty(string, object)
L_000d: nop
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: stfld string SEC.Client.Views.Test::_field
L_0015: ldarg.0
L_0016: ldstr "Field"
L_001b: call instance void [System.ServiceModel.DomainServices.Client]System.ServiceModel.DomainServices.Client.Entity::RaisePropertyChanged(string)
L_0020: nop
L_0021: ret
我的代码:
// Generate a private field
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, type,
FieldAttributes.Private);
// Generate a public property
PropertyBuilder property =
typeBuilder.DefineProperty(propertyName,
PropertyAttributes.None,
type,
new Type[] { type });
if(attributes != null)
{
foreach(var attribute in attributes)
{
property.SetCustomAttribute(attribute);
}
}
// The property set and property get methods require a special set of attributes:
MethodAttributes GetSetAttr =
MethodAttributes.Public |
MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr =
typeBuilder.DefineMethod("get_value",
GetSetAttr,
type,
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[] { type });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Nop);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldstr, propertyName);
currSetIL.Emit(OpCodes.Ldarg_1);
var m = typeof(Entity).GetMethod("ValidateProperty",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, new [] {typeof(string), typeof(object)}, null);
currSetIL.EmitCall(OpCodes.Call, m, null);
currSetIL.Emit(OpCodes.Nop);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldstr, propertyName);
m = typeof(Entity).GetMethod("RaisePropertyChanged",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
currSetIL.EmitCall(OpCodes.Call, m, null);
currSetIL.Emit(OpCodes.Nop);
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);
I'm n00b in IL language. In my task i have to create dynamic types inherited from System.ServiceModel.DomainServices.Client.Entity
. When i am adding additional code to set method of property, i receive "operation could destabilize the runtime". Help me, please, resolve that problem.
Code from Reflector:
L_0000: nop
L_0001: ldarg.0
L_0002: ldstr "Field"
L_0007: ldarg.1
L_0008: call instance void [System.ServiceModel.DomainServices.Client]System.ServiceModel.DomainServices.Client.Entity::ValidateProperty(string, object)
L_000d: nop
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: stfld string SEC.Client.Views.Test::_field
L_0015: ldarg.0
L_0016: ldstr "Field"
L_001b: call instance void [System.ServiceModel.DomainServices.Client]System.ServiceModel.DomainServices.Client.Entity::RaisePropertyChanged(string)
L_0020: nop
L_0021: ret
My code:
// Generate a private field
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, type,
FieldAttributes.Private);
// Generate a public property
PropertyBuilder property =
typeBuilder.DefineProperty(propertyName,
PropertyAttributes.None,
type,
new Type[] { type });
if(attributes != null)
{
foreach(var attribute in attributes)
{
property.SetCustomAttribute(attribute);
}
}
// The property set and property get methods require a special set of attributes:
MethodAttributes GetSetAttr =
MethodAttributes.Public |
MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr =
typeBuilder.DefineMethod("get_value",
GetSetAttr,
type,
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[] { type });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Nop);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldstr, propertyName);
currSetIL.Emit(OpCodes.Ldarg_1);
var m = typeof(Entity).GetMethod("ValidateProperty",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, new [] {typeof(string), typeof(object)}, null);
currSetIL.EmitCall(OpCodes.Call, m, null);
currSetIL.Emit(OpCodes.Nop);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldstr, propertyName);
m = typeof(Entity).GetMethod("RaisePropertyChanged",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
currSetIL.EmitCall(OpCodes.Call, m, null);
currSetIL.Emit(OpCodes.Nop);
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,如果您在之前添加 box 指令:就可以了
:
Yes, it works if you add the box instruction:
before:
这将获取字符串和值/类型的列表,并从中获取 make 和对象。
This will take a list of strings and values/Types and make and object from it.
添加盒子指令后,一切正常。
After adding box instruction, all is fine.