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


312

typeの値で、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ですか?


1
あなたへの質問:これはカスタムORMソリューションの一部ですか?
user3308043 2014年

回答:


527

使用できます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);

以下の@AliKaracaの回答を確認してください。これと以下のものはどちらも速くて緩いですが、一般的なタイプの仕事をします。
アーロンフドン

AはありますTryChangeTypeCanChangeType
Shimmy Weitzhandler

34

他のいくつかの人が言ったように、あなたは使いたいConvert.ChangeType

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

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

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


1
OPはおそらく、文字列からの明らかな変換を持つ任意のタイプのプロパティを設定するための一般的な答えを求めています。
Daniel Earwicker、2009

いい視点ね。私は本当の回答者を編集してポイントするか、誰かが名前空間の残りの部分について私が言ったことを追加する場合は私のものを削除します。
ジョンサンダース

19

多くの人が推奨していることに気づきました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


13

私は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);
}

このケースに遭遇したので、ありがとうと言わなければなりません。これが唯一の解決策です。ありがとう〜!
フランバ

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

コードを整理するという点では、次のようなコードになるようなミックスインを作成できます。

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 { ... }

使用するだけでなく、マーカーinsterfaceを追加した特別な理由はありますobjectか?
Groo

1
はい、マーカーインターフェイスは、拡張メソッドを追加するためのプレースホルダーとして機能します。を使用objectすると、すべてのクラスに拡張メソッドが追加されますが、これは一般的に望ましくありません。
ジョルダン

6

あなたはおそらく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);

5

Convert.ChangeTypeから変換するタイプを使用および取得するPropertyInfo.PropertyType

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

4

一般的な答えでこれに答えます。通常、これらの回答はguidsでは機能しません。こちらも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); 

1
これは受け入れられる答えになるはずです。また、GUID <3でも機能します。おかげで、(私の娘のニックネームです)アリ
カタリンRădoi

3

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

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

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

2

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

0

次のコードを使用すると、問題が解決するはずです。

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

-9

Reflectionで遊んでみませんか?それとも、ソフトウェアのプロダクション作品を構築したいですか?プロパティを設定するためにリフレクションを使用しているのはなぜでしょうか。

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;

1
あなたは人々がやろうとしていることを尊重するべきであり、あなたが彼らがしなければならないことを考えているのではありません。反対投票。(からGenericProgramming.exe:ReflectionBenefits()
ПетърПетров
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.