有没有办法将IEnumerable <t>视为params T []对象?

时间:2015-11-04 16:10:39

标签: c# params system.reflection

我想编写将SQL Server过程结果作为DataTable对象返回的通用代码。然后我编写了下面的代码,但是,我偶然发现了DataTable.Rows.Add()期望params object []参数的问题,而我必须传递的是IEnumerable。

    public static DataTable GetProcedureResults(int id)
    {
        return GetQueryResultAsDataTable<MyProcedure_Result>(_sqlServerDB.MyProcedure(id));
    }

    private static DataTable GetQueryResultAsDataTable<T>(ObjectResult<T> objectResult)
    {
        DataTable resultAsDataTable = new DataTable("Result");
        var columns = typeof(T).GetProperties();
        foreach (var column in columns)
        {
            resultAsDataTable.Columns.Add(column.Name, typeof(string));
        }

        foreach (var resultRecord in objectResult)
        {
            var fields = resultRecord.GetType().GetProperties().Select(p => p.GetValue(resultRecord).ToString());
            resultAsDataTable.Rows.Add(fields);
        }

        return resultAsDataTable;
    }

对于那些熟悉这个问题的人,你可能已经猜到我的数据表在最后看起来像:

enter image description here

这些值都被视为单个对象,因此都被插入第1列。

这里有什么解决方法,如果有的话?我在其他帖子中看到,似乎C#6将修复这个问题,除此之外没有找到一个清晰简洁的解决方案。

2 个答案:

答案 0 :(得分:4)

如果你有一个IEnumerable<T>而一个方法需要一个T[],只需在你的枚举上调用ToArray

var fields = resultRecord.GetType().GetProperties().Select(p => p.GetValue(resultRecord).ToString());
resultAsDataTable.Rows.Add(fields.ToArray());

定义params而不是IEnumerable<T>的{​​{1}}参数的能力最终没有进入C#6(请参阅Eric Lippert's answer about the feature,其链接到公告功能从C#6中删除。然而,即使具有该理论特征,在这种情况下也无济于事。该功能允许API的设计者(例如撰写DataRowCollection.Add的人)接受T[]而不是IEnumerable<T>,如果他们愿意的话(在这种情况下,他们几乎肯定不会,因为它将是一个无声的突破性变化)。它不允许您将T[]传递给期望IEnumerable<T>的方法。作为方法的调用者,如果你没有使用参数的T[]属性(即传递单个参数而不是集合),那么它只是一个采用数组的“普通”方法,而你'负责将你的论证转换为预期的类型。

答案 1 :(得分:1)

您实际上可以将数组传递给params object[],因此临时解决方案可能只是:

var fields = resultRecord.GetType().GetProperties()
                                   .Select(p => p.GetValue(resultRecord).ToString())
                                   .ToArray();
resultAsDataTable.Rows.Add(fields);