2010-10-12 33 views
0

Je suis n00b en langage IL. Dans ma tâche, je dois créer des types dynamiques hérités de System.ServiceModel.DomainServices.Client.Entity. Quand j'ajoute du code supplémentaire pour définir la méthode de propriété, je reçois "l'opération pourrait déstabiliser le runtime". Aidez-moi, s'il vous plaît, à résoudre ce problème.EmitCall soulève "opération pourrait déstabiliser l'exécution" dans Silverlight

code de réflecteur:

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 

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

Répondre

0

Après avoir ajouté l'instruction de la boîte, tout ira bien.

+0

Bonjour, Pouvez-vous poster le code plz? –

3

Oui, il fonctionne si vous ajoutez l'instruction de la boîte:

currSetIL.Emit(OpCodes.Box, type); 

avant:

currSetIL.EmitCall(OpCodes.Call, m, null); 
1

Cela prendra une liste de chaînes et valeurs/Types et faire et l'objet de celle-ci.

using System; 


public class CreateObject 
{ 
    public static object CreatePropertyObject(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object>> objData) 
    { 
     System.Collections.Generic.Dictionary<string, Type> list = new System.Collections.Generic.Dictionary<string, Type>(); 
     foreach (var o in objData) 
     { 
      list.Add(o.Key, o.Value.GetType()); 
     } 

     Type newType = BuildPropertyObject(list); 
     object newObject = NewPropertyObject(newType, objData); 
     return newObject; 
    } 

    public static object NewPropertyObject(Type newType, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object>> objData) 
    { 
     var newObject = Activator.CreateInstance(newType); 
     foreach (var item in objData) 
     { 
      // Set the value on the new object 
      newObject.GetType().GetProperty(item.Key).SetValue(newObject, item.Value, null); 
     } 
     return newObject; 
    } 

    public static Type BuildPropertyObject(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Type>> obj) 
    { 
     string nameOfDLL = "magic.dll"; 
     string nameOfAssembly = "magic_Assembly"; 
     string nameOfModule = "magic_Module"; 
     string nameOfType = "magic_Type"; 

     System.Reflection.AssemblyName assemblyName = new System.Reflection.AssemblyName { Name = nameOfAssembly }; 
     System.Reflection.Emit.AssemblyBuilder assemblyBuilder = System.Threading.Thread.GetDomain().DefineDynamicAssembly(assemblyName, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave); 
     System.Reflection.Emit.ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(nameOfModule, nameOfDLL); 
     System.Reflection.Emit.TypeBuilder typeBuilder = moduleBuilder.DefineType(nameOfType, System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Class); 

     foreach (var prop in obj) 
     { 
      string Name = prop.Key; 
      Type DataType = prop.Value; 

      System.Reflection.Emit.FieldBuilder field = typeBuilder.DefineField("_" + Name, DataType, System.Reflection.FieldAttributes.Private); 
      System.Reflection.Emit.PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(Name, System.Reflection.PropertyAttributes.SpecialName, DataType, null); 
      System.Reflection.MethodAttributes methodAttributes = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.SpecialName; 
      System.Reflection.Emit.MethodBuilder methodBuilderGetter = typeBuilder.DefineMethod("get_" + Name, methodAttributes, DataType, new Type[] { }); 
      System.Reflection.Emit.MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod("set_" + Name, methodAttributes, typeof(void), new Type[] { DataType }); 

      System.Reflection.Emit.ILGenerator ilGeneratorGetter = methodBuilderGetter.GetILGenerator(); 
      ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); 
      ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ldfld, field); 
      ilGeneratorGetter.Emit(System.Reflection.Emit.OpCodes.Ret); 


      System.Reflection.Emit.ILGenerator ilGeneratorSetter = methodBuilderSetter.GetILGenerator(); 
      ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); 
      ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); 
      ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Stfld, field); 
      ilGeneratorSetter.Emit(System.Reflection.Emit.OpCodes.Ret); 

      propertyBuilder.SetGetMethod(methodBuilderGetter); 
      propertyBuilder.SetSetMethod(methodBuilderSetter); 
     } 

     // Yes! you must do this, it should not be needed but it is! 
     Type dynamicType = typeBuilder.CreateType(); 

     // Save to file 
     assemblyBuilder.Save(nameOfDLL); 
     return dynamicType; 
    } 
}