2011-12-24 9 views
10

Ho un file contenente alcune variabili di una classe e ogni riga è una coppia: variabile , valore. Sto cercando un modo per caricare questi in fase di esecuzione (a-la XmlSerializer), utilizzando la riflessione.C# Parse string per digitare noto al runtime

C'è un modo per analizzare uno string in un Type noto solo in fase di esecuzione?

Il seguente è un esempio di codice desiderio dove l'ultima riga (con la pi.SetValue() non è corretto, perché PropertyType è di classe Type che non ha un metodo generico 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); 
    } 
} 

Poiché tutte pertinente le variabili sono Ints, Doubles, Stringhe o Booleans, come ultima risorsa, posso attivare il tipo e utilizzare il metodo ToType() corrispondente, ma scommetto che esiste una soluzione più elegante

risposta

7

È possibile utilizzare il metodo statico Convert.ChangeType per questo. Prende un oggetto come primo parametro e un'istanza Type in cui si desidera convertire l'oggetto. Il valore restituito è del tipo richiesto o nullo se non è stata trovata alcuna conversione adeguata. Questo metodo genera 4 eccezioni diverse, da cui tre sono causate dal valore che tenta di convertire. Potresti prenderli e gestirli.

Utilizzare la funzione come segue nel tuo esempio:

// 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 sono la strada da percorrere. Dai un'occhiata a here per un buon esempio di cosa fare.

intaccate direttamente dal hanselmans blog:

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

+1 a questo come gestirà GUID, Convert.ChangeType non sarà – Arical

+0

Grazie, mi ha aiutato a uscire da una situazione appiccicosa! – Peter

-2

ho avuto lo stesso compito di caricare le variabili di una classe, utilizzando la riflessione. Carico le stringhe di coppie chiave/valore da un file, quindi analizzo i valori in base alle definizioni delle variabili chiave corrispondenti dalla mia classe di impostazioni.

In breve, io uso il seguente codice (metodo FieldInfo.SetValue (Object, Object) è la chiave qui, in quanto non richiede alcuna conversione tipo del valore Object, restituito da TypeConverter.ConvertFromString metodo):

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