360 Stimmen

Einstellung einer Eigenschaft durch Reflexion mit einem String-Wert

Ich möchte eine Eigenschaft eines Objekts über Reflection mit einem Wert des Typs string . Angenommen, ich habe zum Beispiel eine Ship Klasse, mit einer Eigenschaft von Latitude die ein double .

Ich würde gerne Folgendes tun:

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

So wie es ist, führt dies zu einem ArgumentException :

Objekt vom Typ 'System.String' kann nicht in den Typ 'System.Double' konvertiert werden.

Wie kann ich einen Wert in den richtigen Typ konvertieren, basierend auf propertyInfo ?

593voto

LBushkin Punkte 124894

Sie können verwenden Convert.ChangeType() - Es ermöglicht Ihnen die Verwendung von Laufzeitinformationen über jede IConvertible Typ, um die Darstellungsformate zu ändern. Es sind jedoch nicht alle Konvertierungen möglich, und Sie müssen möglicherweise eine spezielle Falllogik schreiben, wenn Sie Konvertierungen von Typen unterstützen wollen, die nicht IConvertible .

Der entsprechende Code (ohne Ausnahmebehandlung oder Sonderfalllogik) würde lauten:

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

36voto

John Saunders Punkte 159011

Wie mehrere andere bereits gesagt haben, sollten Sie die Convert.ChangeType :

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

Ich empfehle Ihnen sogar, sich die gesamte Convert Klasse .

Diese Klasse und viele andere nützliche Klassen sind Teil der System Namespace . Ich finde es nützlich, diesen Namensraum jedes Jahr oder so zu überprüfen, um zu sehen, welche Funktionen ich verpasst habe. Versuchen Sie es doch einmal!

27voto

Ashkan S Punkte 8690

Ich habe die Antwort von LBushkin und es hat gut funktioniert, aber es funktioniert nicht für Nullwerte und nullbare Felder. Also habe ich es folgendermaßen geändert:

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

20voto

Tablet Punkte 4028

Ich stelle fest, dass viele Leute Folgendes empfehlen Convert.ChangeType - Das funktioniert in einigen Fällen, aber sobald man anfängt, die nullable Typen, die Sie erhalten werden InvalidCastExceptions :

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

Vor ein paar Jahren wurde ein Wrapper geschrieben, um dies zu bewerkstelligen, aber auch der ist nicht perfekt.

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

12voto

Jordão Punkte 53117

Sie können einen Typkonverter verwenden (keine Fehlerprüfung):

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

Was die Organisation des Codes angeht, könnten Sie eine Art von Mixin was zu einem Code wie diesem führen würde:

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

Dies würde mit diesem Code erreicht werden:

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 kann für viele verschiedene Klassen wiederverwendet werden.

Sie können auch Ihre eigene benutzerdefinierte Typenkonverter um sie an Ihre Eigenschaften oder Klassen anzuhängen:

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

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X