2012-03-14 73 views
2

JavaScriptSerializerはnull値のエラーを発生させるため、独自のメソッドを作成してオブジェクトグラフをカスタムオブジェクトに変換しています。今PropertyInfo.SetValue()は動作しませんがエラーはありません

internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph) 
{ 
    T generic = (T)Activator.CreateInstance<T>(); 
    Type resType = typeof(T); 
    foreach (PropertyInfo pi in resType.GetProperties()) 
    { 
     object outObj = new object(); 
     if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj)) 
     { 
      Type outType = outObj.GetType(); 
      if (outType == pi.PropertyType) 
      {       
       pi.SetValue(generic, outObj, null); 
      } 
     } 
    } 
    return generic; 
} 

pi.SetValue()メソッドの実行、およびエラーが発生しませんが、私はgenericの性質を見たときにそれがあったとして、それはまだ同じです:

は、これは私がこれまで持っているものです手前に。値がSetValueメソッドを実行した後に続いて、generic.propertyがまだfalseに設定されている。この

generic = an object of type MyCustomType 
generic.property = false 
outObj = true 
pi = boolean property 
outType = boolean 

ように終わるよう

それが経由する最初のプロパティはbooleanです。

+0

無関係ですが、 'generic.GetType()'は私のベンチマークの 'typeof(T)'よりも優れたパフォーマンスを持っています。 'Activator.CreateInstance 'の結果をキャストする理由もなく、既に 'T'のインスタンスを返します。 –

+0

ありがとう、私はそれらのものを変更します。また私は偶然に答えを見つけました。 –

+0

これをデバッグする必要があります。 if(outType == pi.PropertyType)は意味をなさない、あなたが何をしようとしているのかを伝えることはできません。 –

答えて

4

だから私はあなたの方法を取り、それのユニットテストをした:

class PropertySetTest 
{ 
    static readonly Type resType = typeof(Car); 
    internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph) 
    { 
     T generic = (T)Activator.CreateInstance<T>(); 
     foreach (PropertyInfo pi in resType.GetProperties()) 
     { 
      //No need to new() this 
      object outObj; // = new object(); 
      if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj)) 
      { 
       Type outType = outObj.GetType(); 
       if (outType == pi.PropertyType) 
       { 
        pi.SetValue(generic, outObj, null); 
       } 
      } 
     } 
     return generic; 
    } 

    [Test] 
    public void Test() 
    { 
     var typeData = new Dictionary<String, Object> {{"color", "Blue"}}; 
     var myCar = ParseObjectGraph<Car>(typeData); 
     Assert.AreEqual("Blue", myCar.Color); 
    } 
} 

internal class Car 
{ 
    public String Color { get; set; } 
} 

これが通過します。あなたが見ている通りにそれを通過させることはできますか?

編集:あなたの構造体では、わずかに複雑です。何が起こっているかについては、Jon Skeetの答えhereを参照してください。作業コードについて:

class PropertySetTest 
{ 
    static readonly Type resType = typeof(Car); 
    internal static T ParseObjectGraph<T>(Dictionary<string, object> oGraph) 
    { 
     Object generic = Activator.CreateInstance<T>(); 
     foreach (var pi in resType.GetProperties()) 
     { 
      //No need to new() this 
      object outObj; // = new object(); 
      if (oGraph.TryGetValue(pi.Name.ToLower(), out outObj)) 
      { 
       var outType = outObj.GetType(); 
       if (outType == pi.PropertyType) 
        pi.SetValue(generic, outObj, null); 
      } 
     } 
     return (T)generic; 
    } 

    [Test] 
    public void Test() 
    { 
     var typeData = new Dictionary<String, Object> {{"color", "Blue"}}; 
     var myCar = ParseObjectGraph<Car>(typeData); 
     Assert.AreEqual("Blue", myCar.Color); 
    } 
} 

internal struct Car 
{ 
    public String Color { get; set; } 
} 
+0

ありがとう、これが合格した理由は、「車」がクラスだということです。私のオブジェクトは構造体でした。 –

+2

構造体の動作方法については、私の更新を参照してください。 –

+0

それはトリックでした。だから私は実際に 'T'型の'ジェネリック 'をオブジェクトとして使う代わりに、私は本当に何を変えましたか? –

3

答えを見つけました。どうやら、PropertyInfo.SetValue()とPropertyInfo.GetValue()は構造体では機能せず、クラスでしか機能しません。

MyCustomTypeは残念ながら構造体でしたので、これをクラスに変更すると機能しました。

thisの第3の応答では、構造体が機能しない理由とクラスが行う理由について説明しています。

編集:それは構造体で動作します、マークされた答えを見てください。

+1

構造体は機能します。構造体のボックスを解除して元の値を返すのではなく、必ず元の構造体を元に戻す必要があります。それを行う方法は私の答えを参照してください。 –

2

PropertyInfo.SetValue/GetValueメソッドは、構造体を変更する

struct Z 
{ 
    public int X { get; set; } 
} 

    Z z1 = new Z(); 
    z1.GetType().GetProperty("X").SetValue(z1, 100, null); 
    Console.WriteLine(z1.X); //z1.X dont changed 

    object z2 = new Z(); 
    z2.GetType().GetProperty("X").SetValue(z2, 100, null); 
    Console.WriteLine(((Z)z2).X); //z2.x changed to 100 

    Z z3 = new Z(); 
    object _z3 = z3; 
    _z3.GetType().GetProperty("X").SetValue(_z3, 100, null); 
    z3 = (Z)_z3; 
    Console.WriteLine(z3.X); //z3.x changed to 100 

正しい方法を使用して、正確に構造体と協力:

  • ボックス構造体
  • 箱入り構造体
  • アサイン箱入り構造体の変化特性ソースに戻る
関連する問題