2011-12-24 24 views
10

Tengo un archivo que contiene algunas de las variables de una clase, y cada línea es un par: variable , valor. Estoy buscando una manera de cargar estos en tiempo de ejecución (a-la XmlSerializer), usando la reflexión.C# Parse string para escribir conocido en tiempo de ejecución

¿Hay alguna forma de analizar un string en un Type conocido solo en tiempo de ejecución?

El siguiente es un ejemplo de código expresión de deseos, donde la última línea (con la pi.SetValue() no es correcto, porque PropertyType es de la clase Type que no tiene un método genérico Parse().

using (var sr = new StreamReader(settingsFileName)) 
{ 
    String line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     String[] configValueStrs = line.Trim().Split(seps); 

     PropertyInfo pi = configurableProperties 
       .Single(p => p.Name == configValueStrs[0].Trim()); 

     //How do I manage this? 
     pi.SetValue(this, pi.PropertyType.Parse(configValueStrs[1].Trim()), null); 
    } 
} 

ya que todos los relevantes las variables son Ints, Dobles, Strings o Booleans, como último recurso, puedo activar el tipo y usar el método correspondiente ToType(), pero apuesto a que hay una solución más elegante.

Respuesta

7

Puede utilizar el método estático Convert.ChangeType para eso. Toma un objeto como su primer parámetro y una instancia de Type a la que desea convertir el objeto. El valor de retorno es del tipo que solicitó o nulo si no se encontró una conversión adecuada. Este método arroja 4 excepciones diferentes, de las cuales tres son causadas por el valor que intenta convertir. Es posible que desee atrapar y manejar estos.

Utilice la función de la siguiente manera en su ejemplo:

// Convert.ChangeType can throw if the string doesn't convert to any known type 
    pi.SetValue(this 
     , Convert.ChangeType(configValueStrs[1], pi.PropertyType) 
     , null); 
17

TypeConverters son el camino a seguir. Eche un vistazo here para ver un buen ejemplo de qué hacer.

Nicked directamente desde hanselmans blog:

public static T GetTfromString<T>(string mystring) 
{ 
    var foo = TypeDescriptor.GetConverter(typeof(T)); 
    return (T)(foo.ConvertFromInvariantString(mystring)); 
} 
+0

+1 a esto, ya que manejará GUIDS, Convert.ChangeType no se – Arical

+0

¡Gracias, me ayudó a salir de una situación complicada! – Peter

-2

que tenían la misma tarea para cargar las variables de una clase, utilizando la reflexión. Cargué cadenas de par clave/valor de un archivo, luego analizo los valores basándose en las definiciones de las variables clave correspondientes de mi clase de configuración.

En pocas palabras, yo uso el siguiente código (método FieldInfo.SetValue (Object, Object) es la clave aquí, ya que no requiere ningún tipo de conversión del valor Object, devuelto por el método TypeConverter.ConvertFromString):

using System.Reflection; 
using System.ComponentModel; 
using System.Globalization; 

.... 

Settings settings = new Settings(); // my Settings class with variables to load 
FieldInfo[] fields = settings.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static); 
.... 

foreach (var field in fields) 
{ 
    if (key.KeyName == field.Name) 
    { 
     try 
     { 
      field.SetValue(settings, TypeDescriptor.GetConverter(field.FieldType).ConvertFromString(null, CultureInfo.InvariantCulture, key.Value)); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Error: The value string \"{0}\" isn't parsed!", key.Value); 
      //Console.WriteLine(ex.ToString()); 
     } 
     break; 
    } 
}