Merging and combining dynamic/expando objects in C#

I ran into a very interesting situation today where I needed to merge two dynamically created objects in a very similar way to the way that the jQuery Extend method works.

The scenario was that I was creating my own custom override for the MVC DropDownListFor helper and needed to be able to both accept html attributes and had a number of attributes that I wanted to preset.

So the basic method looked like this.

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<System.Func<TModel, TProperty>> expression, string ajaxDataSourceUrl, object htmlAttributes)
{
    dynamic attributes = Merge(new
    {
        @class = "AjaxDropDown",
        data_AjaxDataSourceUrl = ajaxDataSourceUrl,
    }, htmlAttributes);

    MvcHtmlString dropDownList = System.Web.Mvc.Html.SelectExtensions.DropDownListFor(htmlHelper, expression, new List<SelectListItem>(), attributes);
    return dropDownList;
}

The actual Merge method looks like this.

private static dynamic Merge(object item1, object item2)
{
    IDictionary<string, object> result = new ExpandoObject();

    foreach (var property in item1.GetType().GetProperties())
    {
        if (property.CanRead)
            result[property.Name] = property.GetValue(item1);
    }

    foreach (var property in item2.GetType().GetProperties())
    {
        if (property.CanRead)
            result[property.Name] = property.GetValue(item2);
    }

    return result;
}

Note however that the above implementation does not take into account the possibility that both dynamics may contain the same property and in the current implementation will override each other.

Advertisements