Динамически перемещать записи из набора данных в класс, есть ли способ сделать это в C#?

Предполагая, что мы используем это в таблице, используя "выбрать * из таблицы"?

я хочу создать массив классов

которые используют именованные поля (данных) в качестве имен полей классов, инициализируют их полями данных

Является ли это возможным? если так, пожалуйста, помогите:) Соори за орфографию мой письменный английский не так хорош, но я надеюсь, что я был ясен

2 ответа

Решение

Это прекрасное время для использования анонимных типов

var query = (from row in DataTable.Rows.Cast<DataRow>()
            select new 
            {
                 ID = row.Field<int>("ID"),
                 Name = row.Field<string>("Caption"),
                 \\etc etc etc
            }).ToArray();

Если у вас уже есть класс для хранения результатов, вы также можете легко заменить анонимный тип на этот класс (или использовать Tuple в 4.0).

Если вы делаете это часто, вы можете написать метод расширения, который использует отражение, чтобы сопоставить столбцы данных с именами свойств в массиве классов, которые вы пытаетесь сгенерировать.

которые используют именованные поля (данных) в качестве имен полей классов, инициализируют их полями данных

Единственный способ сделать это - сгенерировать класс во время выполнения, что (а) не просто и (б) обычно не очень полезно, потому что код, который будет использовать этот класс, не будет знать имен членов класса.

Вы можете использовать динамические возможности C# 4 для создания списка ExpandoObjects:

Func<DataRow, dynamic> projection =
    r =>
    {
        IDictionary<string, object> exp = new ExpandoObject();
        foreach (DataColumn col in r.Table.Columns)
            exp[col.ColumnName] = r[col];
        return exp;
    };

dynamic[] objects = dataTable.AsEnumerable().Select(projection).ToArray();

...

dynamic o = objects[0];

int id = o.Id;
string name = o.Name;

Но тогда вы теряете преимущества строгой типизации...

Я думаю, что более интересной идеей будет проецирование строк данных в существующие классы на основе имен членов и имен столбцов данных:

public T DataRowToObject<T>(DataRow row) where T : new()
{
    var properties = typeof(T).GetProperties().Where(p => p.CanWrite);
    var columns = row.Table.Columns.Cast<DataColumn>();

    // Match properties of T with DataTable columns
    var common =
        from p in properties
        from c in columns
        where c.ColumnName == p.Name
        && p.PropertyType.IsAssignableFrom(c.DataType)
        select p;

    T obj = new T();
    foreach (var prop in common)
    {
        if (!row.IsNull(prop.Name))
        {
            object value = row[prop.Name];
            prop.SetValue(obj, value, null);
        }
    }
    return obj;
}

...

MyClass[] objects = dataTable.AsEnumerable().Select(row => DataRowToObject(row)).ToArray();
Другие вопросы по тегам