2014-12-05 53 views
0

我試圖通過與下面的代碼字典列表dinamicaly產生的一類:如何創建一個類dynamicaly

public static object CreateCustomObject(List<Dictionary<string, string>> fileProperties) 
{ 
    object result = null; 

    // create the assembly and module 
    AssemblyName assemblyName = new AssemblyName(); 
    assemblyName.Name = "tmpAssembly"; 
    AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
    ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpAssembly"); 

    // create a new type builder 
    TypeBuilder typeBuilder = module.DefineType("CustomObjectToSerialize", TypeAttributes.Public | TypeAttributes.Class); 

    foreach (Dictionary<string, string> _property in fileProperties) 
    { 
     foreach (var _elem in _property) 
     { 
      // create property from file  
      string propertyName = _elem.Key.Replace('.', '_'); 
      FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private); 
      PropertyBuilder property = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, typeof(string), new Type[] { typeof(string) }); 

      MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig; 

      MethodBuilder currGetPropMethBldr = typeBuilder.DefineMethod("get_value", GetSetAttr, typeof(string), Type.EmptyTypes); 

      ILGenerator currGetIL = currGetPropMethBldr.GetILGenerator(); 
      currGetIL.Emit(OpCodes.Ldarg_0); 
      currGetIL.Emit(OpCodes.Ldfld, field); 
      currGetIL.Emit(OpCodes.Ret); 

      MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_value", GetSetAttr, typeof(string), Type.EmptyTypes); 

      ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator(); 
      currSetIL.Emit(OpCodes.Ldarg_0); 
      currSetIL.Emit(OpCodes.Ldarg_1); 
      currSetIL.Emit(OpCodes.Stfld, field); 
      currSetIL.Emit(OpCodes.Ret); 

      property.SetGetMethod(currGetPropMethBldr); 
      property.SetSetMethod(currSetPropMthdBldr); 
     } 
    } 

    Type generatedType = typeBuilder.CreateType(); 
    result = Activator.CreateInstance(generatedType); 
    PropertyInfo[] properties = generatedType.GetProperties(); 

    int propertiesCount = 0; 

    List<string> values = new List<string>(); 
    foreach (Dictionary<string, string> _property in fileProperties) 
    { 
     foreach (var _elem in _property) 
     { 
      //values.Add(_elem.Value); 
      string value = _elem.Value; 
      string propName = _elem.Key.Replace('.', '_'); 
      PropertyInfo pinfo = generatedType.GetProperty(propName); 
      //here I get the error 
      //'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll 
      pinfo.SetValue(result, value); 
      //properties[propertiesCount].SetValue(result, value, null); 
      //propertiesCount++; 
     } 
    } 

    //values.ForEach(_v => 
    //{ 
    // properties[propertiesCount].SetValue(result, _v, null); 
    // propertiesCount++; 
    //}); 

    return result; 
} 

我在嘗試設置屬性的值:

當這個錯誤

mscorlib.dll中發生未處理的「System.Reflection.TargetParameterCountException」異常 附加信息:參數計數不匹配。

我檢查了一下,我在我的示例3屬性中,我將分配3個值。

的代碼截斷並從here

任何想法,適應一下呢?

+1

你爲什麼不使用ExpandoObject類? – 2014-12-05 13:29:41

+0

我沒聽說過。你能解釋一下嗎?謝謝 – blfuentes 2014-12-05 13:30:54

+2

@blacai ExpandoObject最好由[MSDN]解釋(http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v = vs.110).aspx) – Cadde 2014-12-05 13:56:20

回答

1

您已經錯誤地定義了setter方法。您似乎從getter複製/粘貼,沒有正確修改返回類型和參數列表。

雖然getter返回一個值並且沒有參數,但setter不返回任何值(即void)並帶有一個參數。

相反,你必須在你的代碼什麼的,就應該是這樣的:

MethodBuilder currSetPropMthdBldr = 
    typeBuilder.DefineMethod("set_value", GetSetAttr, null, new [] { typeof(string) }); 
+0

我應該檢查更好的時候打字。 – blfuentes 2014-12-08 08:02:28