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

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

其他回答

运行时代码生成与JVM和CLR - 彼得Sestoft

为真正对这类编程感兴趣的人工作。

我给你的建议是,如果你声明了一些东西,尽量避免字符串,所以如果你有类Field,最好使用类System。类型来存储字段类型而不是字符串。 为了最好的解决方案,而不是创建新的类,尝试使用那些已经创建的FiledInfo,而不是创建新的。

哇!谢谢你的回答!我添加了一些功能,以创建一个“数据表到json”的转换器,我与您分享。

    Public Shared Sub dt2json(ByVal _dt As DataTable, ByVal _sb As StringBuilder)
    Dim t As System.Type

    Dim oList(_dt.Rows.Count - 1) As Object
    Dim jss As New JavaScriptSerializer()
    Dim i As Integer = 0

    t = CompileResultType(_dt)

    For Each dr As DataRow In _dt.Rows
        Dim o As Object = Activator.CreateInstance(t)

        For Each col As DataColumn In _dt.Columns
            setvalue(o, col.ColumnName, dr.Item(col.ColumnName))
        Next

        oList(i) = o
        i += 1
    Next

    jss = New JavaScriptSerializer()
    jss.Serialize(oList, _sb)


End Sub

在"compileresulttype" sub中,我修改了:

    For Each column As DataColumn In _dt.Columns
        CreateProperty(tb, column.ColumnName, column.DataType)
    Next


Private Shared Sub setvalue(ByVal _obj As Object, ByVal _propName As String, ByVal _propValue As Object)
    Dim pi As PropertyInfo
    pi = _obj.GetType.GetProperty(_propName)
    If pi IsNot Nothing AndAlso pi.CanWrite Then
        If _propValue IsNot DBNull.Value Then
            pi.SetValue(_obj, _propValue, Nothing)

        Else
            Select Case pi.PropertyType.ToString
                Case "System.String"
                    pi.SetValue(_obj, String.Empty, Nothing)
                Case Else
                    'let the serialiser use javascript "null" value.
            End Select

        End If
    End If

End Sub

你可以使用CSharpProvider:

var code = @"
    public class Abc {
       public string Get() { return ""abc""; }
    }
";

var options = new CompilerParameters();
options.GenerateExecutable = false;
options.GenerateInMemory = false;

var provider = new CSharpCodeProvider();
var compile = provider.CompileAssemblyFromSource(options, code);

var type = compile.CompiledAssembly.GetType("Abc");
var abc = Activator.CreateInstance(type);

var method = type.GetMethod("Get");
var result = method.Invoke(abc, null);

Console.WriteLine(result); //output: abc

您还可以使用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);
}  

我知道我重新打开这个旧任务,但使用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