Вопрос по c#, object, list, .net, dynamic – Создание динамических объектов

7

Как динамически создавать объекты?

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);
}

Imaginary Class(Class is not available in code):

class Employee
{
    string EmpName { get;set; }
    string EmpID { get;set; }
    string PhoneNo { get;set; }
}

Note: Имена свойств / столбцов являются динамическими.

Теперь я хочу преобразоватьList<Dictionary<string, object>> к классу типаList<object> (То есть)List<Employee>.

Является ли это возможным? Предложения, пожалуйста.

@MattBurland У меня есть список & lt; Dictionary & lt; string, object & gt; & gt; что я хочу преобразовать в список & lt; Employee & gt ;. Для объяснения я создал фиктивные данные. Ramesh Durai
объекты могут быть созданы динамически. Тем не менее, кажется, что вы хотите создать тип (Employee) динамически. это верно? Zdeslav Vojkovic
Хотите конвертировать из списка & lt; Dictionary & lt; string, object & gt; & gt; или вы просто хотите создать список & lt; Employee & gt ;? Зачем составлять список словарей в первую очередь? Matt Burland

Ваш Ответ

3   ответа
21

которые хотите проецировать):

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);
}
@TetsujinnoOni должно бытьcolumnValue[j] при установке каждого значения динамического свойства. Вы устанавливаете каждое значение свойства в массиве columnValues
@ZdeslavVojkovic Да! Ты прав. Это была проблема. Ramesh Durai
Взгляните на ExpandoObject и динамическое ключевое слово. (сmsdn.microsoft.com/en-us/library/…) - Я разработаю расширенный ответ с Expando.
Уже отредактировано для создания анонимного класса. Если мы делаем динамические имена свойств, мы превращаемся в совершенно другой шарик воска с гораздо менее простыми ответами, конечно, где DynamicObject начинает быть разумным ответом.
проблема в том, что классEmployee не существует. также имена свойств / столбцов являются динамическими, если я правильно понимаю вопрос
2

В свете того факта, что вы даже не знаете имен столбцов, я бы использовал 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 не прост. :)

Сотрудник - это воображаемый класс. Это не будет доступно в коде. Ramesh Durai
Имена свойств / столбцов являются динамическими. Это была моя проблема. Ramesh Durai
Затем вы можете преобразовать экземпляр класса в анонимный классList<object> newList = testData.Select<object>(p => new {EmpName = p[...etc}); как упоминал Тецудзин в своем примере.
Хм ... Тогда проблема становится намного сложнее. По какой причине вы хотите превратить его в список типизированных свойств? Вы пытаетесь привязать к контролю или что-то?
Да, я хочу привязать к DataGrid (автоматически сгенерированные столбцы). Ramesh Durai
1

Вы можете определять типы динамически, например, с помощьюCodeDOM или используяReflection.Emit, В общем случае ваше приложение будет генерировать модель кода (CodeDOM) или инструкции IL (Reflection.Emit) для создания нового типа. В зависимости от ваших потребностей, вы даже можете сохранить сгенерированные библиотеки DLL и использовать их позже.

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

Похожие вопросы