Динамически перемещать записи из набора данных в класс, есть ли способ сделать это в 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();