Ramesh Durai
Ramesh Durai

Reputation: 2686

Creating Dynamic Objects

How to dynamically create objects?

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: Property/column names are dynamic.

Now I want to convert the List<Dictionary<string, object>> to a class of type List<object> (i.e) List<Employee>.

Is it Possible? Suggestions please.

Upvotes: 7

Views: 32831

Answers (3)

Tetsujin no Oni
Tetsujin no Oni

Reputation: 7367

Using an anonymous object (if you know the properties you want to project):

var employees = 
    (from dict in testData 
        select new 
        { 
            EmpName = dict["EmpName"] as string, 
            EmpID= dict["EmpID"] as string, 
            PhoneNo=dict["PhoneNo"] as string 
        }).ToList();

Or, using System.Dynamic.Expando (if you need to dynamically project unknown column names):

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

Upvotes: 21

Tombala
Tombala

Reputation: 1690

Edited to suggest "Emit".

In light of the fact that you don't even know the column names, I would use Reflection.Emit to first create the Employee class on the fly. See http://msdn.microsoft.com/en-us/library/3y322t50(v=vs.100).aspx for information on how to use Emit. The pseudo code will then be:

ReflectionEmit("Employee", columns);
List<object> newList = testData.Select<object>(p => {
    var employee = ReflectionInstantiate("Employee");
    foreach column in columns
         Reflection.SetProperty(employee, column, p[column]);
    });

The real code will be a little more complicated as Emit is not straightforward. :)

Upvotes: 2

Zdeslav Vojkovic
Zdeslav Vojkovic

Reputation: 14591

Yes it is possible, but not quite simple.

You can define types dynamically, e.g. via CodeDOM or using Reflection.Emit. In general, you application will generate code model (CodeDOM) or IL instrucions (Reflection.Emit) in order to build a new type. Depending on your needs, you can even save the generated dlls and use it later.

This is for example, how serializer assemblies are generated in .NET: the type which is to be serialized is inspected, and custom serializer classes are generated specifically for that type, so that serialization doesn't have to rely on reflection in runtime.

Upvotes: 1

Related Questions