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);