Passing Values to a Function through an Anonymous Type
I’m spending some time looking at ASP.NET MVC. One new common construct I’m seeing is an anonymous type being used to pass property values to a function.
For example, note the third parameter in the method call below:-
routes.MapRoute(
“Default”,
“{controller}/{action}/{id}”,
new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }
);
An anonymous type is being passed to the MapRoute (extension) method that has the following signature.
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
I was surprised to see this because an anonymous class cannot typically be cast to something understandable in the receiving method.
So how then is this achieved? In the case of MVC, the passed in “defaults” object is converted into a Dictionary (a RouteValueDictionary) that contains property names and values determined via reflection.
An Example Implementation
If one wanted to be able to call a method as shown below, it would appear that we have no way to access the properties associated with the “choices” object.
void Main()
{
ProcessChoices( new {marque=”Holden”, model=”Commodore”} );
}public void ProcessChoices(object choices)
{
// choices.marque ? … no
}
However by implementing our own Dictionary we can do so:-
public void ProcessChoices(object choices)
{
var choiceDictionary = new AnonymousObjectDictionary(choices);
Console.WriteLine (choiceDictionary[“marque”]);
}> Holden
A minimal implementation of that AnonymousObjectDictionary is shown below:-
public class AnonymousObjectDictionary : Dictionary<string, object>
{
private readonly Dictionary<string, object> _dictionary;
public AnonymousObjectDictionary(object values)
{
_dictionary = new Dictionary<string, object>();
AddValues(values);
}
private void AddValues(object values)
{
if (values == null)
return;
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(values))
{
object value= propertyDescriptor.GetValue(values);
Add(propertyDescriptor.Name, value);
}
}
}