Frage

Ich möchte eine Eigenschaft eines Objekts durch Reflexion setzen, mit einem Wert vom Typ string. So zum Beispiel, nehme ich eine Ship Klasse, mit einer Eigenschaft von Latitude, die ein double ist.

Hier ist, was ich tun möchte:

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

Wie dies wirft einen ArgumentException:

  

Objekt vom Typ 'System.String' nicht auf den Typ umgewandelt werden 'System.Double'.

Wie kann ich Wert auf den richtigen Typ umwandeln, basierend auf propertyInfo?

War es hilfreich?

Lösung

Sie können mit Convert.ChangeType() - Es ermöglicht Ihnen, Laufzeitinformationen zu verwenden, auf jedem Typ IConvertible Darstellungsformate zu ändern. Nicht alle Konvertierungen sind jedoch möglich, und Sie können Sonderfall Logik schreiben müssen, wenn Sie Konvertierungen von Typen unterstützen möchten, die nicht IConvertible.

Der entsprechende Code (ohne Ausnahmebehandlung oder Sonderfall Logik) 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);

Andere Tipps

Wie mehrere andere gesagt haben, Sie wollen Convert.ChangeType verwenden:

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

In der Tat, empfehle ich Ihnen Blick auf die gesamte Convert Klasse .

Diese Klasse und viele andere nützliche Klassen sind Teil der System Namespace . Ich finde es nützlich, dass die Namespace jedes Jahr oder so zu scannen, um zu sehen, welche Funktionen ich verpasst habe. Probieren Sie es aus!

Ich bemerke eine Menge Leute Convert.ChangeType empfehlen - Dies funktioniert für einige Fälle jedoch, sobald Sie nullable Arten starten denen Sie beginnen InvalidCastExceptions Empfang:

  

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

Es wurde ein Wrapper ein paar Jahre geschrieben vor, dies zu umgehen, aber das ist auch nicht perfekt.

  

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

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

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 Bezug auf den Code der Organisation, könnten Sie ein erstellen Art-of mixin , die in Code wie folgt ergeben würde:

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

Das mit diesem Code erreicht werden würde:

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 eigene erstellen Typ Konverter befestigen auf Ihre Eigenschaften oder Klassen:

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

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

Ich habe versucht, die Antwort von LBushkin und es funktionierte großartig, aber es wird nicht funktionieren für Nullwerte und Nullable-Felder. Also habe ich es so weit 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);
}

Sie suchen wahrscheinlich für die 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);

Mit Convert.ChangeType und immer den Typ aus der PropertyInfo.PropertyType zu konvertieren.

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

Ich beantworte diese mit einer allgemeinen Antwort. Normalerweise werden diese Antworten arbeiten nicht mit guids. Hier ist eine Arbeitsversion mit guids zu.

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

Oder Sie könnten versuchen:

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

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

Wenn Sie Metro App schreiben, sollten Sie einen 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");

statt

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

den folgenden Code verwenden, sollten Sie Ihr Problem lösen:

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

Suchen Sie mit Reflexion zu spielen, um oder suchen Sie ein Produktions Stück Software zu bauen? Ich würde fragen, warum Sie Reflektion verwenden eine Eigenschaft zu setzen.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top