开发者

How do I automap namevaluecollection to a strongly typed class?

I have the configuration details of my application stored in a table like below :

SettingName                   SettingVa开发者_如何学运维lue
--------------------          ---------------------
PostsPerPage                  10   
EmailErrors                   True
AdminEmailAddress             admin@admin.com

My dataaccess class say returns a namevaluecollection / keyvaluepair of settings stored in the table.

What would be best way to map the namevaluecollection /keyvaluepair to a strongly typed class like the one below that has the properties named the same as in SettingName Column.

public class Settings
{
    public int PostsPerPage{get;set;}
    public bool EmailErrors{get;set;}
    public string AdminEmailAddress{get;set;}
}


Here's another shortcut if you have the Newtonsoft Json library in your project - you can use it as a translation mechanism. Not sure if it's all that great performance-wise, but it's very concise and simple...

assume "form" is your "NameValueCollection" object...

// convert to a string/string dictionary and remove anynulls that may have been passed in as a string "null"
var formDictionary = form.AllKeys
                     .Where(p => form[p] != "null")
                     .ToDictionary(p => p, p => form[p]);
string json = JsonConvert.SerializeObject(formDictionary);
var myObject = JsonConvert.DeserializeObject<MyClass>(json);


Use reflection. In pseudo code:

Settings mySettingsClass = new Settings();
foreach (KeyValuePair<string, object> kvp in mySettings) 
{
    PropertyInfo pi = mySettingsClass.GetType().GetProperty(kvp.key, BindingFlags.Public | BindingFlags.Instance);
    if (pi != null) 
    {
        pi.SetValue(mySettingsClass, kvp.Value, null);
    }
}

Of course, if you are reading it back out of a dataReader, then you can take a slightly different approach and avoid using reflection (because the structure of the DataReader and the structure of the target object are known). Using reflection in this case is slower, but is a good way to generically map data from one item to another - basically you take the source property, see if the target property exists on the target object, and then assign the value if it does.


Adding this answer (post is old I know) - had to work off of @slugster's answer - it was the most promising.

NameValueCollection nvc = HttpContext.Current.Request.Form;
Settings mySettingsClass = new Settings();
foreach (string kvp in nvc.AllKeys)
{
    PropertyInfo pi = model.GetType().GetProperty(kvp, BindingFlags.Public | BindingFlags.Instance);
    if (pi != null)
    {
         pi.SetValue(model, nvc[kvp], null);
    }
}

Basically the only difference is @slugster used a KeyValuePair, rather than a NameValueCollection


Use code generation to generate your Settings class. I've done this, and it worked very well. This is the approach I took:

  1. Define your settings in an XML file of your own design. It needs to define at minimum the setting names and types. But you can add other things if you like: help strings, default values, validation predicates, etc.
  2. Use t4 to read in the XML file and generate your Settings class(es). (t4 is a code generator built in to Visual Studio.)

Code generation is often useful in these sorts of cases where you run up against the limitations of static type checking. A nice thing about code generation is that the code is statically typed, so you get compile-time type checking, which of course is one of the benefits of static typing.


Using System.Reflection namespace:

http://www.dotnetspider.com/resources/19232-Set-Property-value-dynamically-using-Reflection.aspx

You get the type using GetType() of an object or do it dynamically, use GetProperties to get all properties from the type or GetProperty to get a single property, and call SetValue with the value from the dictionary.

That's the simplest way. There may be some sort of object mapper that can do this too.

HTH.


NameValueCollection appSettings = ConfigurationManager.AppSettings;
MyProperties myProperties = new MyProperties();

foreach (string setting in appSettings)
{    
    PropertyInfo pi = myProperties.GetType().GetProperty(setting, BindingFlags.Public | BindingFlags.Instance);
    if (pi != null)
    {
        pi.SetValue(myProperties, appSettings.Get(setting), null);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜