7

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.

3
  • 1
    Do you want to convert from List<Dictionary<string,object>> or do you just want to make a List<Employee>? Why make the list of dictionaries in the first place? Commented Sep 14, 2012 at 15:17
  • 1
    objects can be created dynamically. However, it seems that you want to create a type (Employee) dynamically. is that correct? Commented Sep 14, 2012 at 15:17
  • @MattBurland I have a List<Dictionary<string,object>> that I want to convert to List<Employee>. For explanation, I have created a dummy data. Commented Sep 14, 2012 at 15:18

3 Answers 3

20

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);
}
Sign up to request clarification or add additional context in comments.

5 Comments

the problem is that class Employee doesn't exist. also the property/column names are dynamic, if I understand the question correctly
Already edited to create anonymous class. If we're doing dynamic property names we're into a whole different ball of wax with much less straightforward answers, sure, where DynamicObject starts to be a sensible answer.
Take a look at the ExpandoObject and the dynamic keyword. (se msdn.microsoft.com/en-us/library/…) - I'll work up an expanded answer with Expando.
@TetsujinnoOni should be columnValue[j] when setting each dynamic property value. You have it setting each property value to the array of columnValues
@Adam Ahh, right. Extra s that my eye slid right over reviewing your comment. Fixed.
2

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. :)

6 Comments

Employee is an imaginary class. It will not be available in code.
You can then convert the instantiated class to an anonymous class List<object> newList = testData.Select<object>(p => new {EmpName = p[...etc}); as Tetsujin mentioned in his example.
Property/column names are dynamic. That was my problem.
Hmm... Then the problem becomes a lot more complicated. What is the reason you want to turn it into a list of typed properties? Are you trying to bind to a control or something?
Yes I want to bind to DataGrid (Autogenerated Columns).
|
1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.