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
に基づいて、値を適切な型に変換する方法を教えてください。
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);
他の人が言っているように、あなたはConvert.ChangeType
を使いたいのです。
propertyInfo.SetValue(ship,
Convert.ChangeType(value, propertyInfo.PropertyType),
null);
実際、 Convert
Class 全体を見ることをお勧めします。
このクラスや他の多くの便利なクラスは System
ネームスペース の一部です。私が見逃している機能を確認するには、毎年またはその名前空間をスキャンすると便利です。試してみる!
私は多くの人々がConvert.ChangeType
を推薦しているのに気づきます - しかし、nullable
型を使い始めるとすぐにInvalidCastExceptions
を受け取るようになるのでこれはうまくいくでしょう:
これを処理するためにラッパーが数年前に書かれましたが、それも完璧ではありません。
あなたはタイプコンバータを使うことができます(エラーチェックなし):
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 { ... }
私は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);
}
おそらく 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);
Convert.ChangeType
を使用し、PropertyInfo.PropertyType
から変換する型を取得します。
propertyInfo.SetValue( ship,
Convert.ChangeType( value, propertyInfo.PropertyType ),
null );
私は一般的な答えでこれに答えます。通常、これらの答えは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);
またはあなたが試すことができます:
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
//But this will cause problems if your string value IsNullOrEmplty...
あなたが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");
次のコードを使用すると問題が解決します。
item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));