16

オブジェクトのリストが与えられた場合、リスト内の各アイテムが行で表され、各プロパティが行内の列であるデータセットに変換する必要があります。次に、このDataSetは、Excelドキュメントをレポートとして作成するために、 Aspose.Cells関数に渡されます。

私が次を持っているとしましょう:

public class Record
{
   public int ID { get; set; }
   public bool Status { get; set; }
   public string Message { get; set; }
}

Listレコードがある場合、次のようにそれをDataSetに変換するにはどうすればよいですか。

ID Status Message
1  true   "message" 
2  false  "message2" 
3  true   "message3" 
...

現時点で私が考えることができるのは次のとおりです。

DataSet ds = new DataSet
ds.Tables.Add();
ds.Tables[0].Add("ID", typeof(int));    
ds.Tables[0].Add("Status", typeof(bool));
ds.Tables[0].Add("Message", typeof(string));

foreach(Record record in records)
{
    ds.Tables[0].Rows.Add(record.ID, record.Status, record.Message);
}

しかし、この方法では、少なくとも新しいプロパティがRecordに追加された場合、それらはDataSetに表示されないため、より良い方法があるはずだと思います...しかし同時に、それぞれの順序を制御できますプロパティが行に追加されます。

誰かがこれを行うためのより良い方法を知っていますか?

4

5 に答える 5

32

基になる型のプロパティを調べて、リフレクションとジェネリックを使用してそれを行うことができます。

私が使用するこの拡張方法を検討してください。

    public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
    {
        DataTable dt = new DataTable("DataTable");
        Type t = typeof(T);
        PropertyInfo[] pia = t.GetProperties();

        //Inspect the properties and create the columns in the DataTable
        foreach (PropertyInfo pi in pia)
        {
            Type ColumnType = pi.PropertyType;
            if ((ColumnType.IsGenericType))
            {
                ColumnType = ColumnType.GetGenericArguments()[0];
            }
            dt.Columns.Add(pi.Name, ColumnType);
        }

        //Populate the data table
        foreach (T item in collection)
        {
            DataRow dr = dt.NewRow();
            dr.BeginEdit();
            foreach (PropertyInfo pi in pia)
            {
                if (pi.GetValue(item, null) != null)
                {
                    dr[pi.Name] = pi.GetValue(item, null);
                }
            }
            dr.EndEdit();
            dt.Rows.Add(dr);
        }
        return dt;
    }
于 2009-02-07T04:58:23.903 に答える
1

Reflection新しいプロパティを追加するためにクラスのプロパティを決定するためにさらに使用することは別としてRecord、それはほとんどそれです。

于 2009-02-07T04:54:07.330 に答える
0

このタスクを達成するために、私は自分で小さなライブラリを作成しました。リフレクションを使用するのは、オブジェクト型がデータテーブルに変換される最初のときだけです。オブジェクト型を変換するすべての作業を行うメソッドを発行します。

その猛烈な速さ。ここで見つけることができます: GoogleCode の ModelShredder

于 2009-06-18T21:21:20.843 に答える
0

ListにプリミティブまたはString要素が含まれている場合を処理するために、CMS の拡張メソッドにいくつかの変更を加えました。その場合、結果には、リスト内の値ごとにDataTable1 つだけが含まれます。ColumnRow

最初はすべての値型 (プリミティブ型だけでなく) を含めることを考えていましたが、値型である構造体を含めたくありませんでした。

List(Of Long)この変更は、 、 またはをList<long>に変換DataTableして、MS SQL 2008 ストアド プロシージャでテーブル値パラメーターとして使用する必要があったために生じました。

というタグが付いていますが、私のコードは VB で申し訳ありません。私のプロジェクトは VB であり (私の選択ではありません)、C# で変更を適用するのは難しくありません。

Imports System.Runtime.CompilerServices
Imports System.Reflection

Module Extensions

    <Extension()>
    Public Function ToDataTable(Of T)(ByVal collection As IEnumerable(Of T)) As DataTable
        Dim dt As DataTable = New DataTable("DataTable")
        Dim type As Type = GetType(T)
        Dim pia() As PropertyInfo = type.GetProperties()

        ' For a collection of primitive types create a 1 column DataTable
        If type.IsPrimitive OrElse type.Equals(GetType(String)) Then
            dt.Columns.Add("Column", type)
        Else
            ' Inspect the properties and create the column in the DataTable
            For Each pi As PropertyInfo In pia
                Dim ColumnType As Type = pi.PropertyType
                If ColumnType.IsGenericType Then
                    ColumnType = ColumnType.GetGenericArguments()(0)
                End If
                dt.Columns.Add(pi.Name, ColumnType)
            Next

        End If

        ' Populate the data table
        For Each item As T In collection
            Dim dr As DataRow = dt.NewRow()
            dr.BeginEdit()
            ' Set item as the value for the lone column on each row
            If type.IsPrimitive OrElse type.Equals(GetType(String)) Then
                dr("Column") = item
            Else
                For Each pi As PropertyInfo In pia
                    If pi.GetValue(item, Nothing) <> Nothing Then
                        dr(pi.Name) = pi.GetValue(item, Nothing)
                    End If
                Next
            End If
            dr.EndEdit()
            dt.Rows.Add(dr)
        Next
        Return dt
    End Function

End Module
于 2013-01-31T02:57:33.813 に答える