从DataTable中的行创建一系列匿名类型

时间:2011-06-15 20:12:29

标签: c# linq anonymous-types system.data.datatable

这是一个“让我们看看它是否可以完成”运动比其他任何东西都要好。

假设我有一个包含多个列的DataTable。使用linq,是否可以选择表的行,使得结果将是匿名类型的序列,其中匿名类型的每个属性根据DataTable的列名命名,并且每个属性的类型都设置为适当。

因此,如果我的DataTable有三列如此:

Name = "Column1",  DataType = string
Name = "Column2",  DataType = integer
Name = "Column3",  DataType = bool

然后我想选择DataTable的所有行,使匿名类型有三个属性:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => **** MAGIC HERE ****)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

我知道我可以这样做:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => 
   new 
   {
       Column1 = r.Field<string>("Column1"),
       Column2 = r.Field<int>("Column2"),
       Column3 = r.Field<bool>("Column3"),
   }
)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

但这需要对新子句中的属性名称进行硬编码,而我希望属性名称来自DataTable的Columns集合。

我希望我已经清楚地解释了这一点。在稍微讨论了一下之后,我开始认为,就可读性和可维护性而言,我提出的任何事情都会是一团糟,但我想我会问。

2 个答案:

答案 0 :(得分:3)

我担心没有这样的魔法(至少没有匿名类型)。匿名类型是由编译器生成的隐式类型,作为不可变类,其属性名为&amp;通过显式赋值操作键入,如第二个示例中所示(在编译时)。

您想要做的事情需要在运行时构建动态类型。

答案 1 :(得分:2)

正如在Brandon的回答中已经确定的那样,这不能用匿名类型来完成,因为它们是在编译时生成的。但是,如上所述,您可以利用动态来获得类似的语法。

例如,您可以获得以下语法(基于您的示例):

var seq = table.AsEnumerable().Select(row => (dynamic)new DynamicDataRow(row));
foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

为DataRows使用简单的动态包装器:

class DynamicDataRow : DynamicObject
{
    private readonly DataRow row;

    public DynamicDataRow(DataRow row)
    {
        this.row = row;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        DataColumn column = row.Table.Columns[binder.Name];
        if (column != null)
        {
            result = row[column];
            return true;
        }

        result = null;
        return false;
    }
}

我不确定你的用例是什么,但希望如果你认为动态是匿名类型的可接受替代品,这有助于指明你正确的方向。