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 Answer 1

1

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;
}
Sign up to request clarification or add additional context in comments.

4 Comments

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.
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.
+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.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.