tags:

views:

59

answers:

1

Right to the point: How would I map a Dictionary<String, String> to a ViewModel? The ViewModel contains properties of the same name of the Dictionary keys.

To give more information, the program reads a database record and returns all of the values for the record in a Dictionary<String, String>. I only want to display 20-30 of these fields to the user while other processing happens behind the scenes with the other fields. I've made a ViewModel and strongly typed the view. I can manually assign the properties from the Dictionary<String, String> to the ViewModel properties, however this seems like the wrong way to fill the ViewModel.

I then tried using reflection to populate the fields, but again this seems like the wrong way to go about this.

foreach (PropertyInfo propertyInfo in this.GetType().GetProperties())
{
    if (propertyInfo.PropertyType.Name.Equals("String"))
    {
        if (myClass.FieldValues.Keys.Contains(propertyInfo.Name))
        {
            propertyInfo.SetValue(this, myClass.FieldValues[propertyInfo.Name], null);
        }
    }
}

So again, is there a way I can populate my ViewModel using a Dictionary<String, String> where the Key values are the same name as the ViewModel property values?

+1  A: 

If I were I'd be looking at setting up an ORM layer (Entity, Linq-to-Sql) to return strongly typed objects. This provides you with a much more type safe overall solution.

If you are stuck with Dictionary<string,string> then you have three options:

  1. Reflection - you've already done that, that's pretty straight forward.

  2. Expressions/Reflection. You can compile an expression that does the conversion into a lambda once and simply call it as a method afterwards. This has the benefit of being faster at runtime than reflection. However, unless you are doing thousands of these operations per second, performance gained is not worth the extra effort.

  3. dynamic/ExpandoObject. This somewhat experimental and would involve a strongly typed wrapper around a dynamic object.

public class ViewModel {
  ExpandoObject m_Dynamic;

  public string FirstName {return m_Dynamic.FirstName ; }
  public string LastName {return m_Dynamic.LastName; }

  public ExpandoObject DynamicObject {get{return m_Dynamic;}}
}

// In the data mapping layer
ViewModel vm = new ViewModel();
Dictionary<string,string> data = new Dictionary<string,string>{{"FirstName", "Igor"}, {"LastName", "Zevaka"}};
foreach(var kv in data) {
  ((IDictionary<string,object>)vm.DynamicObject)[kv.Key] = kv.Value;
}

Heck, you can even not bother with dynamic and have the property go to the dictionary dicrectly:

public class ViewModel {
  Dictionary<string,string> m_Dynamic;

  public string FirstName {return m_Dynamic["FirstName"]; }
  public string LastName {return m_Dynamic["LastName"]; }

  public Dictionary<string,string> DynamicObject {get {return m_Dynamic;}}
}

// In the data mapping layer
ViewModel vm = new ViewModel();
Dictionary<string,string> data = new Dictionary<string,string>{{"FirstName", "Igor"}, {"LastName", "Zevaka"}};
foreach(var kv in data) {
  vm.DynamicObject[kv.Key] = kv.Value;
}
Igor Zevaka
ViewPage<ExpandoObject> is ok, but ViewPage<dynamic> will cause an access error because all properties in a dynamic variable are internal which can't be accessed in the view.
Danny Chen
In both cases the view inherits from ViewPage<ViewModel>, which should be fine. The view will always work with strongly typed model, it's the implementation of the properties that invokes dynamic objects, not the view.
Igor Zevaka
+1 for detailing the ExpandoObject. I can't say if it's the most appropriate here but I'm glad it's being used in examples so more people are aware of the .NET 4.0 capabilities.
David Neale
I didn't reply right away as I was trying to wrap my head around the ExpandoObject you had mentioned. Using the properties to read directly from the Dictionary<String, String> is so simple. I think that might actually work for what I need it to do.
Neil