如何动态创建一个类

时间:2014-12-05 13:22:45

标签: c# reflection

我正在尝试使用以下代码通过词典列表生成一个类dinamicaly:

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

尝试设置属性值时出现此错误。:

类型为&#39; System.Reflection.TargetParameterCountException&#39;的未处理异常发生在mscorlib.dll中 附加信息:参数计数不匹配。

我检查过,我的样本中有3个属性,我将分配3个值。

代码被采用并且稍微改编自here

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您已错误地定义了setter方法。您似乎已从getter中复制/粘贴,而未正确修改返回类型和参数列表。

当getter返回一个值并且没有参数时,setter不返回任何值(即void)并且接受一个参数。

而不是代码中的内容,它应该如下所示:

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