3

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?

8
  • what language are you using? you tagged C# but some of your code is Java (i.e System.out.printline) - .NET does not have this. Commented Sep 16, 2015 at 8:16
  • I didn't copy paste any code. I just can't remember what it's called in C#. This is pure C# and nothing else. My apologies. Will correct Commented Sep 16, 2015 at 8:18
  • possible duplicate of C# setting/getting the class properties by string name Commented Sep 16, 2015 at 8:19
  • 1
    Just create a List<Dictionary<string, object>>. If you serialize that to JSON with, say, Json.NET, you will get what you want. Commented Sep 16, 2015 at 8:21
  • 2
    @GSerg Which ExpandoObject is :) Commented Sep 16, 2015 at 8:22

5 Answers 5

10

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

8 Comments

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)
Dictionaries would be pretty useless if you couldn't add data after you created them @Detilium.
@dbc for some reason my Json looks like this: [{\"ID\":1,\"Product\":\"Honning\",\"Days\":1,\"QTY\":65}]
@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.
@dbc I did double serialize. Everything works now. Thank you for spending time in here. I really appreciate it
|
1

As you can see here ExpandoObject Class, the ExpandoObject is implementing IDictionary<string, object>, so you can use that fact like

IDictionary<string, object> obj = new ExpandoObject();
var propName = "Product";
obj[propName] = "Pie"
Console.WriteLine("Let's print!: " + obj[propName]);
// Verify it's working
Console.WriteLine("Let's print again!: " + ((dynamic)obj).Product);

Comments

1

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)

Comments

1

While I was writing the answer, I see you already got proper answer. You can use a Dictionary<string, onject> or even Tuple.

But as per your original question, you wanted to add properties dynamically. For that you can refer to other answer using ExpandoObject. This is just the same solution (using ExpandoObject to dynamically add properties) with classes similar to your code.

//example classes
public class DictKey
{
    public string DisplayName { get; set; }
    public DictKey(string name) { DisplayName = name; }
}

public class DictValue
{
    public int ColumnIndex { get; set; }
    public DictValue(int idx) { ColumnIndex = idx; }
}

//utility method
public static IDictionary<string, object> GetExpando(KeyValuePair<DictKey, List<DictValue>> dictPair)
{
    IDictionary<string, object> dynamicObject = new ExpandoObject();
    dynamicObject["Station"] = dictPair.Key.DisplayName;
    foreach (var item in dictPair.Value)
    {
        dynamicObject["Month" + (item.ColumnIndex + 1)] = item;
    }
    return dynamicObject;
}

Ans usage example:

var dictionaryByMonth = new Dictionary<DictKey, List<DictValue>>();
dictionaryByMonth.Add(new DictKey("Set1"), new List<DictValue> { new DictValue(0), new DictValue(2), new DictValue(4), new DictValue(6), new DictValue(8) });
dictionaryByMonth.Add(new DictKey("Set2"), new List<DictValue> { new DictValue(1), new DictValue(2), new DictValue(5), new DictValue(6), new DictValue(11) });

var rowsByMonth = dictionaryByMonth.Select(item => GetExpando(item));

Comments

0

First part, read this blog post by C# team thoroughly.

Lets see your code

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

var obj.propName = "Pie"

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

//OUTPUT
Let's print!: Pie

In your code you are using var obj = new ExpandoObject();, so you are creating a statically typed object of type ExpandableObject. In the blog they specifically call out

I didn’t write ExpandoObject contact = new ExpandoObject(), because if I did contact would be a statically-typed object of the ExpandoObject type. And of course, statically-typed variables cannot add members at run time. So I used the new dynamic keyword instead of a type declaration, and since ExpandoObject supports dynamic operations, the code works

So if you rewrite your code to use dynamic obj, and add the dynamic properties as properties it should work!

But for your particular use case you better use Dictionaries as suggested above by @dbc

dynamic obj = new ExpandoObject();
obj.Product= "Pie"    
Console.WriteLine("Let's print!: " + obj.Product);    
//OUTPUT
Let's print!: Pie

2 Comments

Neither his nor your code will work. They will not even compile. When you get them to compile by removing an unwanted var and adding a missing ;, you will see it does not do what you expect and throws an exception instead of printing "Pie", because this code adds property propName to obj, not property Product.
c**p, i noticed only the static type as the problem. will edit my answer to fix them too. I don't have access to Visual studio at the moment, came to SO for something else, saw this!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.