2010-10-12 3 views
0

Я n00b на языке ИЛ. В моей задаче я должен создать динамические типы, унаследованные от System.ServiceModel.DomainServices.Client.Entity. Когда я добавляю дополнительный код для установки метода свойства, я получаю «операция может дестабилизировать время выполнения». Помогите мне решить эту проблему.EmitCall повышает «операция может дестабилизировать время выполнения» в Silverlight

Код от рефлектора:

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

ответ

0

После добавления инструкции коробки, все в порядке.

+0

Здравствуйте, Можете ли вы опубликовать код PLZ? –

3

Да, это работает, если вы добавляете инструкцию коробки:

currSetIL.Emit(OpCodes.Box, type); 

до:

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

Это займет список строк и значений/Типы и сделать и из него объектный.

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