2012-11-07 4 views
16

long?のプロパティはintで埋められます。リフレクトを使用してプロパティを設定するときの型変換の問題

私はちょうどobj.Value = v;直接プロパティを設定しますが、私は試してみて、反射info.SetValue(obj, v, null);を通じてプロパティを設定すると、それは私に次の例外を与えたときにこれが正常に動作します:タイプの

オブジェクトの可能System.Int32 'にすることはできませんタイプ 'System.Nullable`1 [System.Int64]'に変換されます。

これは単純化したシナリオです:直接プロパティを設定するとき、それが動作しながら、reflectionてプロパティを設定するとき

class TestClass 
    { 
     public long? Value { get; set; } 
    } 

    [TestMethod] 
    public void TestMethod2() 
    { 
     TestClass obj = new TestClass(); 
     Type t = obj.GetType(); 

     PropertyInfo info = t.GetProperty("Value"); 
     int v = 1; 

     // This works 
     obj.Value = v; 

     // This does not work 
     info.SetValue(obj, v, null); 
    } 

なぜそれが機能しないのですか?

答えて

48

チェック記事全文:How to set value of a property using Reflection?

完全なコードあなたはあなたがあなたの財産の型に値を変換する必要があり、このすなわちのように値を変換する必要があり

public static void SetValue(object inputObject, string propertyName, object propertyVal) 
{ 
    //find out the type 
    Type type = inputObject.GetType(); 

    //get the property information based on the type 
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName); 

    //find the property type 
    Type propertyType = propertyInfo.PropertyType; 

    //Convert.ChangeType does not handle conversion to nullable types 
    //if the property type is nullable, we need to get the underlying type of the property 
    var targetType = IsNullableType(propertyInfo.PropertyType) ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; 

    //Returns an System.Object with the specified System.Type and whose value is 
    //equivalent to the specified object. 
    propertyVal = Convert.ChangeType(propertyVal, targetType); 

    //Set the value of the property 
    propertyInfo.SetValue(inputObject, propertyVal, null); 

} 
private static bool IsNullableType(Type type) 
{ 
    return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)); 
} 

NULL可能タイプの値を設定する場合以下のようになります

PropertyInfo info = t.GetProperty("Value"); 
object value = null; 
try 
{ 
    value = System.Convert.ChangeType(123, 
     Nullable.GetUnderlyingType(info.PropertyType)); 
} 
catch (InvalidCastException) 
{ 
    return; 
} 
propertyInfo.SetValue(obj, value, null); 

あなたが書くとき、指定された型に任意のarbirtary値を変換することはできません...ので、あなたはこの

+0

優秀な回答!! – series0ne

+0

遅れて申し訳ありませんが、あなたのコードサンプルを使いこなしていました。これはトリックでした、ありがとう! – Shikyo

+0

'null'を設定すると動作しません。修正は簡単ですが、あなたの投稿を編集しようとしましたが、拒否されました。 – Shikyo

2

のようにそれを変換する必要があります。

obj.Value = v; 

コンパイラはあなたのための適切なキャスティングを行う方法を知っていて、実際に

コンパイル
obj.Value = new long?((long) v); 

あなたの使用を反映しているときは、あなたを助けるコンパイラはありません。

2

タイプlongには暗黙的な変換方法があるためです。

6.1.2 Implicit numeric conversions

あなたは=シンボルの後ろに隠れて存在する方法として、暗黙的な変換方法を見ることができます。

また、NULL可能タイプで作業:

int i = 0; 
int? j = i; // Implicit conversion 
long k = i; // Implicit conversion 
long? l = i; // Implicit conversion 

しかし、暗黙の変換が非nullにnullを渡すために存在しないので、周りに動作しません、他の道を行く:

int? i = 0; 
int j = i; // Compile assert. An explicit conversion exit... 
int k = (int)i; // Compile, but if i is null, you will assert at runtime. 

intint? ...またはlong?に明示的に変換する必要はありません。

ただし、リフレクションを使用する場合は、暗黙的な変換をバイパスして、値をプロパティに直接割り当てます。このように、明示的に変換する必要があります。

info.SetValue(obj, (long?)v, null); 

反射は、背後に隠されたすべての甘いものをスキップします。=

+0

明確な説明のためにこのような疑いがあります。 – Shikyo

関連する問題