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

16,091

Solution 1

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}]

Solution 2

Use dynamic, then cast to IDictionary<string, object> to loop through your properties:

dynamic obj = new ExpandoObject();
obj.Product = "Pie";
obj.Quantity = 2;

// Loop through all added properties       
foreach(var prop in (IDictionary<string, object>)obj)
{
  Console.WriteLine(prop.Key + " : " + prop.Value);
}

I've made a fiddle: https://dotnetfiddle.net/yFLy2u

Now this is a solution to your question... other answers like @dbc's might be better suited to the problem (which is not the question, really)

Share:
16,091

Related videos on Youtube

Detilium
Author by

Detilium

Updated on June 28, 2022

Comments

  • Detilium
    Detilium almost 2 years

    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?

    • dbc
      dbc almost 9 years
      Just create a List<Dictionary<string, object>>. If you serialize that to JSON with, say, Json.NET, you will get what you want.
    • Patrick Hofman
      Patrick Hofman almost 9 years
      @GSerg Which ExpandoObject is :)
  • Detilium
    Detilium almost 9 years
    Won't really work in my case as I don't have all values available, but I need to loop through them. Could you give an example? var valueList = allRowValues and var clumn = allClumnNames (Working on an edit of main question)
  • aelveborn
    aelveborn almost 9 years
    Dictionaries would be pretty useless if you couldn't add data after you created them @Detilium.
  • Detilium
    Detilium almost 9 years
    @dbc for some reason my Json looks like this: [{\"ID\":1,\"Product\":\"Honning\",\"Days\":1,\"QTY\":65}]
  • aelveborn
    aelveborn almost 9 years
  • dbc
    dbc almost 9 years
    @Detilium - you're probably looking at it in Visual Studio which is "helpfully" escaping the quotes in the string. To see it without quotes, type Debug.WriteLine(myString) in the immediate window. Or print it to the console. Also, answer updated with an example of how to build a dictionary incrementally.
  • Detilium
    Detilium almost 9 years
    Yes it does actually look like this as I'm using Postman (google Extension) as I mentioned in the main question (not using the console in VS) Postman shows the raw output I get. It doesn't care about VS. If \ is in the string Postman shows the \
  • dbc
    dbc almost 9 years
    @Detilium - There's no mention of Postman anywhere in this question, so I'm not sure what that's about -- your question has Console.WriteLine(). But if you're posting this somehow, you may be double-serializing your JSON somehow.
  • Detilium
    Detilium almost 9 years
    @dbc I did double serialize. Everything works now. Thank you for spending time in here. I really appreciate it