Создание динамических объектов
Как динамически создавать объекты?
string[] columnNames = { "EmpName", "EmpID", "PhoneNo" };
List<string[]> columnValues = new List<string[]>();
for (int i = 0; i < 10; i++)
{
columnValues.Add(new[] { "Ramesh", "12345", "12345" });
}
List<Dictionary<string, object>> testData = new List<Dictionary<string, object>>();
foreach (string[] columnValue in columnValues)
{
Dictionary<string, object> data = new Dictionary<string, object>();
for (int j = 0; j < columnNames.Count(); j++)
{
data.Add(columnNames[j], columnValues[j]);
}
testData.Add(data);
}
Воображаемый класс (класс не доступен в коде):
class Employee
{
string EmpName { get;set; }
string EmpID { get;set; }
string PhoneNo { get;set; }
}
Примечание. Имена свойств / столбцов являются динамическими.
Теперь я хочу преобразовать List<Dictionary<string, object>>
к классу типа List<object>
(То есть) List<Employee>
,
Является ли это возможным? Предложения, пожалуйста.
3 ответа
Использование анонимного объекта (если вы знаете свойства, которые хотите проецировать):
var employees =
(from dict in testData
select new
{
EmpName = dict["EmpName"] as string,
EmpID= dict["EmpID"] as string,
PhoneNo=dict["PhoneNo"] as string
}).ToList();
Или, используя System.Dynamic.Expando (если вам нужно динамически проецировать неизвестные имена столбцов):
string[] columnNames = { "EmpName", "EmpID", "PhoneNo" };
List<string[]> columnValues = new List<string[]>();
for (int i = 0; i < 10; i++)
{
columnValues.Add(new[] { "Ramesh", "12345", "12345" });
}
var testData = new List<ExpandoObject>();
foreach (string[] columnValue in columnValues)
{
dynamic data = new ExpandoObject();
for (int j = 0; j < columnNames.Count(); j++)
{
((IDictionary<String,Object>)data).Add(columnNames[j], columnValue[j]);
}
testData.Add(data);
}
Отредактировано, чтобы предложить "Emit".
В свете того факта, что вы даже не знаете имен столбцов, я бы использовал Reflection.Emit, чтобы сначала создать класс Employee на лету. См. http://msdn.microsoft.com/en-us/library/3y322t50(v=vs.100).aspx для получения информации о том, как использовать Emit. Тогда псевдокод будет:
ReflectionEmit("Employee", columns);
List<object> newList = testData.Select<object>(p => {
var employee = ReflectionInstantiate("Employee");
foreach column in columns
Reflection.SetProperty(employee, column, p[column]);
});
Реальный код будет немного сложнее, так как Emit не так прост.:)
Да, это возможно, но не совсем просто.
Вы можете определять типы динамически, например, через CodeDOM или используя Reflection.Emit. Как правило, ваше приложение будет генерировать модель кода (CodeDOM) или инструкции IL (Reflection.Emit) для создания нового типа. В зависимости от ваших потребностей, вы даже можете сохранить сгенерированные библиотеки DLL и использовать их позже.
Например, как сборки сериализатора генерируются в.NET: проверяется тип, который должен быть сериализован, и пользовательские классы сериализатора генерируются специально для этого типа, так что сериализация не должна полагаться на отражение во время выполнения.