C# - Adding objects dynamically (adding dynamic property names)

Detilium picture Detilium · Sep 16, 2015 · Viewed 14.9k times · Source

I'm trying to create some dynamic ExpandoObject. I've encountered a certain problem.

As I don't know what the name of these different properties in my objects should be, I can't do like this:

var list = new ArrayList();

var obj = new ExpandoObject();
obj.ID = 1,
obj.Product = "Pie",
obj.Days = 1,
obj.QTY = 65

list.Add(obj);

Let me explain my situation: I wish to get data from a random DB (I don't know which, but building a connection string from the information I get from the UI), therefore I don't know what data I need to get. This could be an example of a DB table

TABLE Sale

  • ID: int,
  • Product: nvarchar(100),
  • Days: int,
  • QTY: bigint

This could be another exmaple:

TABLE Foobar

  • Id: int,
  • Days: int
  • QTY: bigint
  • Product_Id: int
  • Department_Id: int

As you see, I don't know what the DB looks like (this is 100% anonymous, therefore it needs to be 100% dynamic), and the data I want to return should look like a well constructed JSON, like so:

[
  {
    "ID": 1,
    "Product": "Pie"
    "Days": 1,
    "QTY": 65
  },
  {
    "ID": 2,
    "Product": "Melons"
    "Days": 5,
    "QTY": 12
  }
]

Or, with the other example:

[
  {
    "ID": 1,
    "Days": 2,
    "QTY": 56,
    "Product_Id": 5,
    "Department_Id": 2
  }
  {
    "ID": 2,
    "Days": 6,
    "QTY": 12,
    "Product_Id": 2,
    "Department_Id": 5
  }
]

I've tried working with these ExpandoObjects, but can't seem to make it work, as I can't do what's illustrated in the top of this question (I don't know the names of the properties). Is there a way for me to say something like:

var obj = new ExpandoObject();
var propName = "Product";

var obj.propName = "Pie"

Console.WriteLine("Let's print!: " + obj.Product);

//OUTPUT
Let's print!: Pie

Does anyone have a solution, og simply guidance to a structure, that might solve this situation?

Answer

dbc picture dbc · Sep 16, 2015

Rather than creating an ExpandoObject or some other dynamic type, you could create a List<Dictionary<string, object>> where each Dictionary<string, object> contains the name/value pairs you want to serialize. Then serialize to JSON using Json.NET (or JavaScriptSerializer, though that is less flexible):

        var list = new List<Dictionary<string, object>>();

        // Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx
        list.Add(new Dictionary<string, object> { { "ID", 1 }, {"Product", "Pie"}, {"Days", 1}, {"QTY", 65} });

        // Build a dictionary entry incrementally
        // See https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
        var dict = new Dictionary<string, object>();
        dict["ID"] = 2;
        dict["Product"] = "Melons";
        dict["Days"] = 5;
        dict["QTY"] = 12;
        list.Add(dict);

        Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
        Console.WriteLine(new JavaScriptSerializer().Serialize(list));

The first outputs:

[
  {
    "ID": 1,
    "Product": "Pie",
    "Days": 1,
    "QTY": 65
  },
  {
    "ID": 2,
    "Product": "Melons",
    "Days": 5,
    "QTY": 12
  }
]

The second outputs the same without the indentation:

[{"ID":1,"Product":"Pie","Days":1,"QTY":65},{"ID":2,"Product":"Melons","Days":5,"QTY":12}]