282


76

文字列値を使用したリフレクションによるプロパティの設定

タイプ `+ string `の値で、Reflectionを介してオブジェクトのプロパティを設定したいと思います。 したがって、たとえば、プロパティが「 Latitude 」、つまり「 double 」である「 Ship +」クラスがあるとします。

これが私のやりたいことです。

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

そのまま、これは `+ ArgumentException +`をスローします:

_ タイプ 'System.String’のオブジェクトは、タイプ 'System.Double’に変換できません。 _

`+ propertyInfo +`に基づいて、値を適切な型に変換するにはどうすればよいですか?

11 Answer


469


http://msdn.microsoft.com/en-us/library/ms130977.aspx [+ Convert.ChangeType()+]を使用できます - 任意の `+ IConvertible `タイプでランタイム情報を使用できます 表現形式を変更します。 ただし、すべての変換が可能なわけではなく、 ` IConvertible +`ではない型からの変換をサポートする場合は、特殊なケースのロジックを記述する必要があります。

対応するコード(例外処理または特別な場合のロジックなし)は次のようになります。

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


32


他のいくつかの人が言ったように、 `+ Convert.ChangeType +`を使いたい:

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

実際、http://msdn.microsoft.com/en-us/library/system.convert.aspx [+ Convert + Class]全体を参照することをお勧めします。

このクラス、および他の多くの有用なクラスは、http://msdn.microsoft.com/en-us/library/system.aspx [+ System + Namespace]の一部です。 私が見逃している機能を確認するには、毎年またはその名前空間をスキャンするのが便利です。 試してみる!


18


多くの人が `+ Convert.ChangeType `を推奨していることに気付きました-これはいくつかのケースで機能しますが、 ` nullable `型を使用し始めるとすぐに ` InvalidCastExceptions +`を受け取り始めます:

これを処理するためにラッパーが数年前に書かれましたが、それも完璧ではありません。


11


あなたはタイプコンバータを使うことができます(エラーチェックなし):

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

コードを整理するという点では、http://codecrafter.blogspot.com/2010/02/c-quasi-mixins-pattern.html[kind-of mixin]を作成すると、次のようなコードになります。

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

これは次のコードで実現されます。

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 +`は、さまざまなクラスで再利用できます。

独自のカスタムhttp://msdn.microsoft.com/en-us/library/ayybcxe5.aspx [type converters]を作成して、プロパティやクラスに関連付けることもできます。

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

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


6


おそらくhttp://msdn.microsoft.com/en-us/library/dtb69x08.aspx [+ Convert.ChangeType +]メソッドを探しています。 例えば:

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


6


私は* LBushkin *から答えを試してみました、そしてそれはうまくいきました、しかしそれはnull値とnull許容可能なフィールドのために働かないでしょう。 だから私はこれをこれに変更しました:

propertyName = "緯度"; PropertyInfo propertyInfo = ship.GetType()。GetProperty(propertyName); if(propertyInfo!= null){タイプt = Nullable.GetUnderlyingType(propertyInfo.PropertyType)} propertyInfo.PropertyType;オブジェクトsafeValue =(value == null)? null:Convert.ChangeType(value、t); propertyInfo.SetValue(ship、safeValue、null); }


5


`+ Convert.ChangeType `を使用し、 ` PropertyInfo.PropertyType +`から変換するタイプを取得します。

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


3


またはあなたが試すことができます:

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

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


2


あなたがMetroアプリを書いているなら、あなたは他のコードを使うべきです:

シップシップ= new Ship();文字列値= "5.5"; PropertyInfo propertyInfo = ship.GetType()。GetTypeInfo()。GetDeclaredProperty( "Latitude"); propertyInfo.SetValue(ship、Convert.ChangeType(value、propertyInfo.PropertyType));

注意:

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

の代わりに

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


2


私は一般的な答えでこれに答えます。 通常、これらの答えはguidではうまくいきません。 これもguidを使った作業バージョンです。

var stringVal = "6e3ba183-89d9-e611-80c2-00155dcfb231"; //設定する文字列としてのguid値//設定するプロパティvar propType = prop.PropertyType;

// var will be type of guid here
var valWithRealType = TypeDescriptor.GetConverter(propType).ConvertFrom(stringVal);