it-swarm.com.de

Festlegen einer Eigenschaft durch Reflektion mit einem Zeichenfolgenwert

Ich möchte eine Eigenschaft eines Objekts über Reflection mit einem Wert vom Typ string festlegen. Angenommen, ich habe eine Ship -Klasse mit der Eigenschaft Latitude, bei der es sich um eine double handelt.

Folgendes möchte ich tun:

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

Wie es ist, wirft dies ein ArgumentException:

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

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

291
David Hodgson

Sie können Convert.ChangeType() - verwenden, um Laufzeitinformationen für jeden IConvertible -Typ zu verwenden, um Darstellungsformate zu ändern. Es sind jedoch nicht alle Konvertierungen möglich, und Sie müssen möglicherweise eine Sonderfalllogik schreiben, wenn Sie Konvertierungen von Typen unterstützen möchten, die nicht IConvertible sind.

Der entsprechende Code (ohne Ausnahmebehandlung oder Sonderfalllogik) wäre:

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

Wie einige andere gesagt haben, möchten Sie Convert.ChangeType:

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

In der Tat empfehle ich, dass Sie sich die gesamte Convert-Klasse ansehen.

Diese Klasse und viele andere nützliche Klassen sind Teil des Namensraums System . Ich finde es nützlich, diesen Namespace jedes Jahr zu scannen, um festzustellen, welche Funktionen ich vermisst habe. Versuche es!

33
John Saunders

Ich stelle fest, dass viele Leute Convert.ChangeType Empfehlen - Dies funktioniert in einigen Fällen jedoch, sobald Sie anfangen, nullable Typen einzubeziehen, werden Sie anfangen, InvalidCastExceptions zu erhalten:

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

Ein Wrapper wurde vor ein paar Jahren geschrieben, um damit umzugehen, aber das ist auch nicht perfekt.

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

19
Tablet

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

Um den Code zu organisieren, könnten Sie ein eine Art Mixin erstellen, das zu folgendem Code 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 eigenen benutzerdefinierten Typkonverter erstellen, um sie an Ihre Eigenschaften oder Klassen anzuhängen:

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

[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
11
Jordão

Ich habe die Antwort von LBushkin ausprobiert und es hat großartig funktioniert, aber es funktioniert nicht für Nullwerte und nullfähige 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);
}
9
Ashkan Sirous

Sie suchen wahrscheinlich nach dem Convert.ChangeType Methode. Zum Beispiel:

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

Mit Convert.ChangeType und den zu konvertierenden Typ aus dem PropertyInfo.PropertyType.

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

Ich werde dies mit einer allgemeinen Antwort beantworten. Normalerweise funktionieren diese Antworten nicht mit Guids. Hier ist auch eine funktionierende Version mit Anleitungen.

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); 
4
Ali Karaca

Oder Sie könnten versuchen:

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

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

Wenn Sie eine Metro-App schreiben, sollten Sie anderen Code verwenden:

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

Hinweis:

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

anstatt von

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

Die Verwendung des folgenden Codes sollte Ihr Problem lösen:

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