web-dev-qa-db-ja.com

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

Reflectionを通じて、オブジェクトのプロパティをstring型の値で設定します。したがって、たとえば、Shipというプロパティを持つLatitudeクラスがあり、これがdoubleであるとします。

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

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に基づいて、値を適切な型に変換する方法を教えてください。

285
David Hodgson

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

他の人が言っているように、あなたはConvert.ChangeTypeを使いたいのです。

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

実際、 Convert Class 全体を見ることをお勧めします。

このクラスや他の多くの便利なクラスは Systemネームスペース の一部です。私が見逃している機能を確認するには、毎年またはその名前空間をスキャンすると便利です。試してみる!

32
John Saunders

私は多くの人々がConvert.ChangeTypeを推薦しているのに気づきます - しかし、nullable型を使い始めるとすぐにInvalidCastExceptionsを受け取るようになるのでこれはうまくいくでしょう:

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

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

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

19
Tablet

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

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

コードを整理するという点では、 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は、さまざまなクラスで再利用できます。

独自のカスタム タイプコンバーター を作成して、プロパティやクラスに添付することもできます。

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

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

私はLBushkinから答えを試してみましたが、うまくいきましたが、null値やnull値の可能なフィールドに対してはうまくいきません。だから私はこれをこれに変更しました:

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

おそらく 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
John Calsbeek

Convert.ChangeTypeを使用し、PropertyInfo.PropertyTypeから変換する型を取得します。

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

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

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

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

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

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

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

Ship ship = new Ship();
string value = "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
Serhiy

次のコードを使用すると問題が解決します。

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