2010-02-25 13 views
6

tengo los detalles de la configuración de mi solicitud almacenan en una tabla como la siguiente:¿Cómo automatizo namevaluecollection en una clase fuertemente tipada?

SettingName     SettingValue 
--------------------   --------------------- 
PostsPerPage     10 
EmailErrors     True 
AdminEmailAddress    [email protected] 

Mi clase DATAACCESS decir devuelve un NameValueCollection/KeyValuePair de configuración almacenados en la tabla.

¿Cuál sería la mejor manera de asignar el namevaluecollection/keyvaluepair a una clase fuertemente tipada como la siguiente que tiene las mismas propiedades que en SettingName Column.

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

¿Hay alguna razón es necesario utilizar este formato extraño en lugar de utilizar app.config/web.config? –

Respuesta

2

Use la reflexión. En pseudocódigo:

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); 
    } 
} 

Por supuesto, si usted está leyendo de nuevo fuera de una dataReader, entonces puede tomar un enfoque ligeramente diferente y evitar el uso de la reflexión (debido a que la estructura del objeto DataReader y la estructura de la diana objeto son conocidos). El uso de la reflexión en este caso es más lento, pero es una buena forma de mapear genéricamente datos de un elemento a otro: básicamente toma la propiedad de origen, ve si la propiedad de destino existe en el objeto de destino y luego asigna el valor si lo hace.

+0

Gracias por el pseudo código ... Sé que puedo hacerlo con la reflexión, pero esperaba saber si hay otras opciones sobre cómo puedo hacerlo. Me quedaré con la reflexión por ahora y veré cómo funciona. – Sam

0

El uso de espacio de nombres System.Reflection:

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

obtener el tipo usando GetType() de un objeto o lo hace de forma dinámica, GetProperties utilizar para obtener todas las propiedades de la clase o de GetProperty obtener una sola propiedad y llamar a SetValue con el valor del diccionario.

Esa es la forma más sencilla. Puede haber algún tipo de mapeador de objetos que pueda hacer esto también.

HTH.

1

Usa la generación de código para generar tu clase de Configuraciones. He hecho esto, y funcionó muy bien. Este es el enfoque que tomé:

  1. Define tus configuraciones en un archivo XML de tu propio diseño. Necesita definir como mínimo los nombres y tipos de configuración. Pero puede agregar otras cosas si lo desea: cadenas de ayuda, valores predeterminados, predicados de validación, etc.
  2. Utilice t4 para leer en el archivo XML y generar sus clases de configuración (es). (t4 es un generador de código incorporado en Visual Studio.)

La generación de código suele ser útil en este tipo de casos en los que se encuentra con las limitaciones de la comprobación de tipo estático. Lo bueno de la generación de código es que el código está tipado estáticamente, por lo que obtienes la verificación de tipos en tiempo de compilación, que por supuesto es uno de los beneficios del tipado estático.

+0

Me gusta la idea, pero en mi caso todas mis configuraciones están basadas en bases de datos. – Sam

+0

@Sam, el objetivo es generar código C# a partir de los metadatos. Realmente no importa de dónde provienen esos metadatos. Puede generar C# desde un volcado de su tabla, o desde donde se definan los metadatos para su configuración. –

2

Agregando esta respuesta (la publicación es antigua, lo sé) - tuvo que funcionar con la respuesta de @ slugster - fue la más prometedora.

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); 
    } 
} 

Básicamente, la única diferencia es utilizado @slugster un KeyValuePair, en lugar de un NameValueCollection

1

Aquí hay otro acceso directo si usted tiene la biblioteca Newtonsoft JSON en su proyecto - que se puede utilizar como un mecanismo de traducción. No estoy seguro de si es tan bueno en cuanto a rendimiento, pero es muy conciso y simple ...

asumen "forma" es su objeto "NameValueCollection" ...

// 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); 
Cuestiones relacionadas