Search code examples
c#recursionexpandoobjectidictionarydynamicobject

In C#, how do I change a Key-Value-Property's value while recursively traversing an ExpandoObject?


The Problem

Using C#, I need to traverse an object that has been cast to an ExpandoObject from XML and replace any "price" property with a new value.

This object is very unstructured and has many layers of nested nodes (nested ExpandoObjects, actually). More specifically, the hierarchy may look like this:

Product => price, quantity, accessories

Each accessory may have a price and quantity and may itself have accessories, this is why I need recursion.

What I have so far

  public ExpandoObject UpdatePricing(ExpandoObject exp)
    {
        //Is there a price property?
        var hasPrice = exp.Any(a => a.Key == "price");
        if (hasPrice)
        {
            //update price here
            exp.price = 0; //Some other price
        }

        //Now loop through the whole object.  If any of the properties contain an expando, then call this method again
        foreach (var kvp in exp)
        {
            if (kvp.Value is ExpandoObject)
            {
                //THIS CODE IS NO GOOD BECAUSE kvp.Value has no setter!!
                kvp.Value = UpdatePricing(kvp.Value);
            }
        }

        return exp;
    }

The problem I run into is that the kvp.Value has no setter, so I can't run this method recursively.

Any suggestions are appreciated. Thanks!


Solution

  • Since ExpandoObject implements IDictionary<string, Object> things can get a bit easier. We can also change the return type to void because we don't need to reassign the result.

    void UpdatePrice(ExpandoObject expando, decimal price)
    {
        var map = (IDictionary<string, Object>)expando;
        if (map.ContainsKey("price"))
            map["price"] = price;
        foreach (var value in map.Values) 
        {
            if (value is ExpandoObject)
                UpdatePrice((ExpandoObject)value, price);
        }
    }