我有一个类,它看起来像这样:

public class Field
{
    public string FieldName;
    public string FieldType;
}

和一个对象列表<字段>值:

{"EmployeeID","int"},
{"EmployeeName","String"},
{"Designation","String"}

我想创建一个类,看起来像这样:

Class DynamicClass
{
    int EmployeeID,
    String EmployeeName,
    String Designation
}

有什么办法可以做到吗?

我希望它在运行时生成。我不希望在文件系统中驻留一个物理CS文件。


当前回答

我不知道这种动态类的预期用途,代码生成和运行时编译是可以完成的,但需要一些努力。 也许匿名类型会帮助你,比如:

var v = new { EmployeeID = 108, EmployeeName = "John Doe" };

其他回答

我知道我重新打开这个旧任务,但使用c# 4.0这个任务是绝对无痛的。

dynamic expando = new ExpandoObject();
expando.EmployeeID=42;
expando.Designation="unknown";
expando.EmployeeName="curt"

//or more dynamic
AddProperty(expando, "Language", "English");

更多信息请参见 https://www.oreilly.com/learning/building-c-objects-dynamically

你可以使用system . runtime . remoting . agents . realproxy。它将允许您使用“正常”代码,而不是低级程序集类型的东西。

请参阅RealProxy对这个问题的回答,以获得一个好例子:

我如何拦截一个方法调用在c# ?

我不知道这种动态类的预期用途,代码生成和运行时编译是可以完成的,但需要一些努力。 也许匿名类型会帮助你,比如:

var v = new { EmployeeID = 108, EmployeeName = "John Doe" };

您还可以使用DynamicExpressions动态地创建类。

因为'Dictionary'有紧凑的初始化器并处理键冲突,所以你会想这样做。

  var list = new Dictionary<string, string> {
    {
      "EmployeeID",
      "int"
    }, {
      "EmployeeName",
      "String"
    }, {
      "Birthday",
      "DateTime"
    }
  };

或者,您可能希望使用JSON转换器将序列化的字符串对象构造为可管理的对象。

然后使用System.Linq.Dynamic;

  IEnumerable<DynamicProperty> props = list.Select(property => new DynamicProperty(property.Key, Type.GetType(property.Value))).ToList();

  Type t = DynamicExpression.CreateClass(props);

剩下的就是使用System.Reflection。

  object obj = Activator.CreateInstance(t);
  t.GetProperty("EmployeeID").SetValue(obj, 34, null);
  t.GetProperty("EmployeeName").SetValue(obj, "Albert", null);
  t.GetProperty("Birthday").SetValue(obj, new DateTime(1976, 3, 14), null);
}  

是的,您可以为此使用System.Reflection.Emit命名空间。如果你没有经验,这并不直接,但这当然是可能的。

编辑:这段代码可能有缺陷,但它会给你一个大概的想法,希望能有一个良好的开端。

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace TypeBuilderNamespace
{
    public static class MyTypeBuilder
    {
        public static void CreateNewObject()
        {
            var myType = CompileResultType();
            var myObject = Activator.CreateInstance(myType);
        }
        public static Type CompileResultType()
        {
            TypeBuilder tb = GetTypeBuilder();
            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            // NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
            foreach (var field in yourListOfFields)
                CreateProperty(tb, field.FieldName, field.FieldType);

            Type objectType = tb.CreateType();
            return objectType;
        }

        private static TypeBuilder GetTypeBuilder()
        {
            var typeSignature = "MyDynamicType";
            var an = new AssemblyName(typeSignature);
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
                    TypeAttributes.Public |
                    TypeAttributes.Class |
                    TypeAttributes.AutoClass |
                    TypeAttributes.AnsiClass |
                    TypeAttributes.BeforeFieldInit |
                    TypeAttributes.AutoLayout,
                    null);
            return tb;
        }

        private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
        {
            FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

            PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator getIl = getPropMthdBldr.GetILGenerator();

            getIl.Emit(OpCodes.Ldarg_0);
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);
            getIl.Emit(OpCodes.Ret);

            MethodBuilder setPropMthdBldr =
                tb.DefineMethod("set_" + propertyName,
                  MethodAttributes.Public |
                  MethodAttributes.SpecialName |
                  MethodAttributes.HideBySig,
                  null, new[] { propertyType });

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();
            Label modifyProperty = setIl.DefineLabel();
            Label exitSet = setIl.DefineLabel();

            setIl.MarkLabel(modifyProperty);
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Stfld, fieldBuilder);

            setIl.Emit(OpCodes.Nop);
            setIl.MarkLabel(exitSet);
            setIl.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }
}