Domanda

Mi piacerebbe impostare una proprietà di un oggetto attraverso la riflessione, con un valore di tipo string. Così, per esempio, supponiamo di avere una classe 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);

Come è, questo getta un ArgumentException:

  

Oggetto di tipo 'System.String' non può essere convertito nel tipo 'System.Double'.

Come posso convertire il valore per il tipo corretto, sulla base di propertyInfo?

È stato utile?

Soluzione

È possibile utilizzare Convert.ChangeType() - Esso consente di utilizzare informazioni di runtime su qualsiasi tipo IConvertible cambiare formati di rappresentazione. Non tutte le conversioni sono possibili, però, e potrebbe essere necessario scrivere la logica speciale caso, se si desidera supportare conversioni da tipi che non sono IConvertible.

Il corrispondente codice (senza manipolazione eccezione o logica speciale caso) sarebbe:

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

Altri suggerimenti

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

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

In realtà, io consiglio di guardare l'intero Convert Classe .

Questa classe, e molte altre classi utili sono parte della System Namespace . Trovo utile per la scansione di quel namespace ogni anno o giù di lì per vedere cosa caratteristiche che ho perso. Provatelo!

Ho notato un sacco di persone stanno suggerendo Convert.ChangeType - Questo funziona per alcuni casi, tuttavia, non appena si inizia a coinvolgere i tipi nullable si inizierà a ricevere InvalidCastExceptions:

  

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

Un wrapper è stato scritto alcuni anni fa per gestire questo, ma che non è perfetto sia.

  

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

È possibile utilizzare un convertitore di tipi (senza 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, è possibile creare un tipo-di mixin che si tradurrebbe in codice come questo:

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

Questo potrebbe essere 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 riutilizzata per molte classi diverse.

È anche possibile creare il proprio personalizzato convertitori di tipi per attaccare alle proprietà o classi:

public class Ship : MPropertyAsStringSettable {
  public Latitude Latitude { get; set; }
  // ...
}

[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }

Ho cercato la risposta da LBushkin e ha funzionato grande, ma non funziona per i valori nulli e campi Null. Così ho cambiato in questo modo:

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

Utilizzando Convert.ChangeType e ottenere il tipo di convertire dal PropertyInfo.PropertyType.

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

risponderò questo con una risposta generale. Di solito queste risposte non si lavora con GUID. Ecco una versione di lavoro con GUID troppo.

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

Oppure si potrebbe provare:

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

//But this will cause problems if your string value IsNullOrEmplty...

Se si sta scrivendo Metro app, è necessario utilizzare 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");

anziché

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

utilizzando il seguente codice dovrebbe risolvere il problema:

item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));

Stai cercando di giocare con la riflessione o stai cercando di costruire un pezzo produzione di software? Mi chiedo perché si sta utilizzando la riflessione per impostare una proprietà.

Double new_latitude;

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