ExpandoObject 转换为 DataTable

3

我是新手ExpandoObject(事实上,我昨天才了解它)。 我有以下代码,想知道是否有某种方法可以将ExpandoObject转换为DataTable? 或者我必须使用反射来自己转换它?

dynamic contacts = new List<dynamic>();

contacts.Add(new ExpandoObject());
contacts[0].Name = "Patrick Hines";
contacts[0].Phone = "206-555-0144";

contacts.Add(new ExpandoObject());
contacts[1].Name = "Ellen Adams";
contacts[1].Phone = "206-555-0155";

1
ExpandoObject 实现了 IDictionary<string, object> 接口,因此您可以使用任何将字典转换为 DataTable 的代码。 - Jeroen Mostert
2个回答

6

这是我需要转换它的方法。但如果有更好的方法,请告诉我。

    public DataTable ToDataTable(IEnumerable<dynamic> items)
    {
        var data = items.ToArray();
        if (data.Count() == 0) return null;

        var dt = new DataTable();
        foreach (var key in ((IDictionary<string, object>)data[0]).Keys)
        {
            dt.Columns.Add(key);
        }
        foreach (var d in data)
        {
            dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
        }
        return dt;
    }

只要您的对象都具有相同的属性(否则,推断表结构会更加困难),这就可以工作。但是,如果是这样,为什么要首先使用 ExpandoObject 呢?您可以声明一个类来保存数据,这对可维护性有积极影响。class Contact { public string Name { get; set; } public string Phone { get; set; } } 并不需要输入太多内容。 - Jeroen Mostert
也许我可以从你这里得到一些帮助,以更好地构建我的代码。我正在处理一个复杂模型的列表,其中包含一个列表。我之所以在模型内部有一个子列表,是因为选择是多选的,它返回一个ID列表。我需要将其展平成数据表,然后进行批量复制到数据库中。因此,创建一个动态对象来保存此模型,并添加一个新属性来保存ID的连接字符串。ID的连接字符串最终存储在数据库中的列/字段中,如1,2,3。我愿意听取关于将嵌套列表展平为数据表的建议。 - NKD
这听起来像是一个非常具体的场景,需要比我们在评论中能提供的更多。请尝试使用代码审查 - Jeroen Mostert
@JeroenMostert 谢谢。 - NKD

0
你可以使用这段代码。Linq会帮助你 :)
var contacts = new List<dynamic>();

contacts.Add(new ExpandoObject());
contacts[0].Name = "Patrick Hines";
contacts[0].Phone = "206-555-0144";

contacts.Add(new ExpandoObject());
contacts[1].Name = "Ellen Adams";
contacts[1].Phone = "206-555-0155";
// DataTable Instance...
DataTable table = new DataTable();

//Get all properties of contract list items
var properties = contacts.GetType().GetProperties();

// Remove contract list property
properties = properties.ToList().GetRange(0, properties.Count() - 1).ToArray();

// Add column as named by property name
properties.ToList().ForEach(p => table.Columns.Add(p.Name,typeof(string)));

// Add rows from contracts list
contacts.ForEach(x =>  table.Rows.Add(x.Name,x.Phone));

使用LINQ做得非常好。我选择了另一种选项,因为我希望在将来重复使用该方法。你的方法很好,但如果我需要转换其他内容,我不想重新输入它(例如指定属性名称x.Name、x.Phone)。感谢您抽出时间来查看这个问题。 - NKD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接