【问题标题】:Creating Dynamic Objects创建动态对象
【发布时间】:2012-09-07 18:45:36
【问题描述】:

如何动态创建对象?

string[] columnNames = { "EmpName", "EmpID", "PhoneNo" };
List<string[]> columnValues = new List<string[]>();
for (int i = 0; i < 10; i++)
{
    columnValues.Add(new[] { "Ramesh", "12345", "12345" });
}

List<Dictionary<string, object>> testData = new List<Dictionary<string, object>>();

foreach (string[] columnValue in columnValues)
{
    Dictionary<string, object> data = new Dictionary<string, object>();
    for (int j = 0; j < columnNames.Count(); j++)
    {
        data.Add(columnNames[j], columnValues[j]);
    }
    testData.Add(data);
}

虚构类(类在代码中不可用):

class Employee
{
    string EmpName { get;set; }
    string EmpID { get;set; }
    string PhoneNo { get;set; }
}

注意:属性/列名是动态的。

现在我想将List&lt;Dictionary&lt;string, object&gt;&gt; 转换为List&lt;object&gt; 类型的类(即List&lt;Employee&gt;

有可能吗?请提出建议。

【问题讨论】:

  • 您想从 List> 转换还是只想制作一个 List?为什么首先要列出字典?
  • 对象可以动态创建。但是,您似乎想动态创建一个类型 (Employee)。对吗?
  • @MattBurland 我有一个 List>,我想将它转换为 List。为了解释,我创建了一个虚拟数据。

标签: c# .net list object dynamic


【解决方案1】:

使用匿名对象(如果您知道要投影的属性):

var employees = 
    (from dict in testData 
        select new 
        { 
            EmpName = dict["EmpName"] as string, 
            EmpID= dict["EmpID"] as string, 
            PhoneNo=dict["PhoneNo"] as string 
        }).ToList();

或者,使用 System.Dynamic.Expando(如果您需要动态投影未知列名):

string[] columnNames = { "EmpName", "EmpID", "PhoneNo" };
List<string[]> columnValues = new List<string[]>();
for (int i = 0; i < 10; i++)
{
    columnValues.Add(new[] { "Ramesh", "12345", "12345" });
}

var testData = new List<ExpandoObject>();

foreach (string[] columnValue in columnValues)
{
    dynamic data = new ExpandoObject();
    for (int j = 0; j < columnNames.Count(); j++)
    {
        ((IDictionary<String,Object>)data).Add(columnNames[j], columnValue[j]);
    }
    testData.Add(data);
}

【讨论】:

  • 问题是Employee 类不存在。如果我正确理解问题,属性/列名也是动态的
  • 已经编辑创建匿名类。如果我们正在使用动态属性名称,我们将陷入一个完全不同的蜡球,答案不那么简单,当然,DynamicObject 开始成为一个明智的答案。
  • 看看 ExpandoObject 和 dynamic 关键字。 (se msdn.microsoft.com/en-us/library/…) - 我会用 Expando 来扩展答案。
  • @TetsujinnoOni 在设置每个动态属性值时应该是columnValue[j]。您可以将每个属性值设置为 columnValues 数组
  • @Adam Ahh,对。额外的s,我的眼睛滑过审查你的评论。固定。
【解决方案2】:

编辑建议“发射”。

鉴于您甚至不知道列名,我将使用 Reflection.Emit 首先动态创建 Employee 类。有关如何使用 Emit 的信息,请参阅 http://msdn.microsoft.com/en-us/library/3y322t50(v=vs.100).aspx。伪代码将是:

ReflectionEmit("Employee", columns);
List<object> newList = testData.Select<object>(p => {
    var employee = ReflectionInstantiate("Employee");
    foreach column in columns
         Reflection.SetProperty(employee, column, p[column]);
    });

实际代码会稍微复杂一些,因为 Emit 并不简单。 :)

【讨论】:

  • Employee 是一个虚构的类。它在代码中不可用。
  • 然后您可以将实例化的类转换为匿名类 List&lt;object&gt; newList = testData.Select&lt;object&gt;(p =&gt; new {EmpName = p[...etc});,正如 Tetsujin 在他的示例中提到的那样。
  • 属性/列名是动态的。那是我的问题。
  • 嗯...那么问题就变得复杂多了。你想把它变成一个类型化属性列表的原因是什么?你是想绑定控件还是什么?
  • 是的,我想绑定到 DataGrid(自动生成的列)。
【解决方案3】:

是的,这是可能的,但不是很简单。

您可以动态定义类型,例如通过CodeDOM 或使用Reflection.Emit。通常,您的应用程序将生成代码模型 (CodeDOM) 或 IL 指令 (Reflection.Emit) 以构建新类型。根据您的需要,您甚至可以保存生成的 dll 供以后使用。

例如,在 .NET 中如何生成序列化程序集:检查要序列化的类型,并专门为该类型生成自定义序列化程序类,因此序列化不必依赖于运行时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    相关资源
    最近更新 更多