Impostazione di una proprietà per riflessione con un valore stringa

Mi piacerebbe impostare una proprietà di un object tramite Reflection, con un valore di tipo string . Quindi, per esempio, supponiamo di avere una class Ship , con una proprietà di Latitude , che è un double .

Ecco cosa mi piacerebbe fare:

 Ship ship = new Ship(); string value = "5.5"; PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude"); propertyInfo.SetValue(ship, value, null); 

Così, questo genera una ArgumentException :

L’object di tipo “System.String” non può essere convertito in tipo “System.Double”.

Come posso convertire il valore nel tipo corretto, in base a propertyInfo ?

È ansible utilizzare Convert.ChangeType() : consente di utilizzare le informazioni di runtime su qualsiasi tipo di IConvertible per modificare i formati di rappresentazione. Tuttavia, non tutte le conversioni sono possibili e potrebbe essere necessario scrivere una logica di caso speciale se si desidera supportare le conversioni da tipi che non sono convertibili.

Il codice corrispondente (senza gestione delle eccezioni o logica dei casi speciali) sarebbe:

 Ship ship = new Ship(); string value = "5.5"; PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude"); propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null); 

Come molti altri hanno detto, si desidera utilizzare Convert.ChangeType :

 propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null); 

In effetti, ti consiglio di guardare l’intera class di Convert .

Questa class e molte altre classi utili fanno parte dello spazio System nomi di System . Trovo utile scansionare quel namespace ogni anno o giù di lì per vedere quali caratteristiche mi sono perso. Provaci!

Ho notato che molte persone raccomandano Convert.ChangeType – Questo funziona per alcuni casi tuttavia, non appena inizi a coinvolgere nullable tipi nullable , inizierai a ricevere InvalidCastExceptions :

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx

Qualche anno fa è stato scritto un wrapper per gestire questo, ma non è nemmeno perfetto.

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx

È ansible utilizzare un convertitore di tipi (nessun controllo degli errori):

 Ship ship = new Ship(); string value = "5.5"; var property = ship.GetType().GetProperty("Latitude"); var convertedValue = property.Converter.ConvertFrom(value); property.SetValue(self, convertedValue); 

In termini di organizzazione del codice, è ansible creare un tipo di mixin che risulterebbe in un codice come questo:

 Ship ship = new Ship(); ship.SetPropertyAsString("Latitude", "5.5"); 

Questo sarebbe stato raggiunto con questo codice:

 public interface MPropertyAsStringSettable { } public static class PropertyAsStringSettable { public static void SetPropertyAsString( this MPropertyAsStringSettable self, string propertyName, string value) { var property = TypeDescriptor.GetProperties(self)[propertyName]; var convertedValue = property.Converter.ConvertFrom(value); property.SetValue(self, convertedValue); } } public class Ship : MPropertyAsStringSettable { public double Latitude { get; set; } // ... } 

MPropertyAsStringSettable può essere riutilizzato per molte classi diverse.

Puoi anche creare i tuoi convertitori di tipi personalizzati da albind alle tue proprietà o classi:

 public class Ship : MPropertyAsStringSettable { public Latitude Latitude { get; set; } // ... } [TypeConverter(typeof(LatitudeConverter))] public class Latitude { ... } 

Probabilmente stai cercando il metodo Convert.ChangeType . Per esempio:

 Ship ship = new Ship(); string value = "5.5"; PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude"); propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null); 

Utilizzando Convert.ChangeType e ottenere il tipo da convertire da PropertyInfo.PropertyType .

 propertyInfo.SetValue( ship, Convert.ChangeType( value, propertyInfo.PropertyType ), null ); 

Ho provato la risposta di LBushkin e ha funzionato benissimo, ma non funzionerà con valori nulli e campi nullable. Quindi l’ho cambiato in questo:

 propertyName= "Latitude"; PropertyInfo propertyInfo = ship.GetType().GetProperty(propertyName); if (propertyInfo != null) { Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; object safeValue = (value == null) ? null : Convert.ChangeType(value, t); propertyInfo.SetValue(ship, safeValue, null); } 

O potresti provare:

 propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null); //But this will cause problems if your string value IsNullOrEmplty... 

Se stai scrivendo Metro app, dovresti usare un altro codice:

 Ship ship = new Ship(); string value = "5.5"; PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude"); propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType)); 

Nota:

 ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude"); 

invece di

 ship.GetType().GetProperty("Latitude"); 

Risponderò a questa con una risposta generale. Di solito queste risposte non funzionano con i guids. Ecco una versione funzionante con guids anche.

 var stringVal="6e3ba183-89d9-e611-80c2-00155dcfb231"; // guid value as string to set var prop = obj.GetType().GetProperty("FooGuidProperty"); // property to be setted var propType = prop.PropertyType; // var will be type of guid here var valWithRealType = TypeDescriptor.GetConverter(propType).ConvertFrom(stringVal); 

Stai cercando di giocare con Reflection o stai cercando di build un software di produzione? Mi chiederei perché stai usando la riflessione per impostare una proprietà.

 Double new_latitude; Double.TryParse (value, out new_latitude); ship.Latitude = new_latitude;