Вопрос

В моем приложении есть метод, который заполняет DataTable данными, используя следующий код:

DataTable dt = this.attachmentsDataSet.Tables["Attachments"];

foreach (Outlook.Attachment attachment in this.mailItem.Attachments)
{
    DataRow dr = dt.NewRow();
    dr["Index"] = attachment.Index;
    dr["DisplayName"] = String.Format(
        CultureInfo.InvariantCulture,
        "{0} ({1})", 
        attachment.FileName,
        FormatSize(attachment.Size));
    dr["Name"] = attachment.FileName;
    dr["Size"] = attachment.Size;

    dt.Rows.Add(dr);
}

Мне было интересно, смогу ли я достичь той же функциональности с помощью LINQ, чтобы немного сократить этот код. Есть идеи?

Это было полезно?

Решение

Ну, этот код не короче или Linq, но я сделал метод расширения, который берет IList и превращает его в DataTable для вас.

    public static DataTable ToDataTable<T>(this IList<T> theList)
    {
        DataTable theTable = CreateTable<T>();
        Type theEntityType = typeof(T);

        // Use reflection to get the properties of the generic type (T)
        PropertyDescriptorCollection theProperties = TypeDescriptor.GetProperties(theEntityType);

        // Loop through each generic item in the list
        foreach (T theItem in theList)
        {
            DataRow theRow = theTable.NewRow();

            // Loop through all the properties
            foreach (PropertyDescriptor theProperty in theProperties)
            {
                // Retrieve the value and check to see if it is null
                object thePropertyValue = theProperty.GetValue(theItem);
                if (null == thePropertyValue)
                {
                    // The value is null, so we need special treatment, because a DataTable does not like null, but is okay with DBNull.Value
                    theRow[theProperty.Name] = DBNull.Value;
                }
                else
                {
                    // No problem, just slap the value in
                    theRow[theProperty.Name] = theProperty.GetValue(theItem);
                }
            }

            theTable.Rows.Add(theRow);
        }

        return theTable;
    }

Другие советы

Да, просто

    public void FillFromList(List<T> col)
    {
        Type elementType = typeof(T);

        // Nested query of generic element list of property
        // values (using a join to the DataTable columns)
        var rows = from row in col
                   select new
                   {
                       Fields = from column in m_dataTable.Columns.Cast<DataColumn>()
                                join prop in elementType.GetProperties()
                                  on column.Caption equals prop.Name
                                select prop.GetValue(row, null)
                   };

        // Add each row to the DataTable
        int recordCount = 0;
        foreach ( var entry in rows )
        {
            m_dataTable.Rows.Add(entry.Fields.ToArray());
        }

Предполагается, что свойства в T такие же, как столбцы DataTable.

Сначала вы определяете, можете ли вы запросить this.mailItem.Attachments и если это возможно, вы можете преобразовать результат запроса в набор данных из метода расширения, созданного с помощью Стив Слока ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top