Dictionary<string,object> to object mapper

1.7k Views Asked by At

Is there any object-object mapper that can map properties from a dictionary (or other name-value collection)?

Let's say I have classes

public class SomeClass
{
    public string Text { get; set; }
    public Address HomeAddress { get; set; }
    public List<int> Numbers { get; set; }
}
public class Address
{
    public string Street { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }    
}

What I would like to do is

var values = new Dictionary<string,object>();
values.Add("Text","Foo");
values.Add("HomeAddress.Street","Some street 123");
values.Add("HomeAddress.PostalCode","12345");
values.Add("HomeAddress.City","Some city");
values.Add("Numbers[0]",123);
values.Add("Numbers[1]",234);
values.Add("Numbers[2]",345);

SomeClass some = aMapperTool.CreateFromDictionary<SomeClass>(values);

That's basically like the DefaultModelBinder in ASP.NET MVC, which requires a lot of context and metadata related stuff and therefore isn't quite handy.

2

There are 2 best solutions below

2
On

You won't get around reflection or expression trees for this.

With reflection, it would be roughly the following:

  1. create an object of T
  2. iterate over the keys in details, if needed, construct the actual property name out of it (HomeAddress.Street -> HomeAdress, or Numbers[0] -> Number). Depending on the type of the property (if you find a ., you need to construct the child object first, if you find a [, you need to initialize an IEnumerable).
  3. after constructing any child structures, construct the parent object.

While this is a possible solution, there is one question going through my head: "Why?"

0
On

You can leverage the ComponentModel functionality (this has been addressed elsewhere in stackoverflow

how to set nullable type via reflection code ( c#)?

using System.ComponentModel;   

public void FillMeUp(Dictionary<string, string> inputValues){

        PropertyInfo[] classProperties  = this.GetType().GetProperties();

       var properties = TypeDescriptor.GetProperties(this);

       foreach (PropertyDescriptor property in properties)
       {
           if (inputValues.ContainsKey(property.Name))
           {
               var value = inputValues[property.Name];
               property.SetValue(this, 
                                 property.Converter.ConvertFromInvariantString(value));
           }
       }