2009-10-10 11 views
14

を通じて一覧 に項目を追加すると、私はある種のデシリアライザに取り組んでいると私はデータから Childリストを作成し、移入することができるようにしたい私は、このクラスに は動的反射

class Child { 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

class Container { 
    public List<Child> { get; set; } 
} 

を考えてみましょう取り出された。私はキャストする方法を見つけ出すことはできません

var props = typeof(Container).GetProperties(); 

foreach (var prop in props) { 
    var type = prop.PropertyType; 
    var name = prop.Name; 

    if (type.IsGenericType) { 
     var t = type.GetGenericArguments()[0]; 

     if (type == typeof(List<>)) { 
      var list = Activator.CreateInstance(type); 
      var elements = GetElements(); 

      foreach (var element in elements) { 
       var item = Activator.CreateInstance(t); 
       Map(item, element); 

       // ??? how do I do list.Add(item) here? 
      } 

      prop.SetValue(x, list, null); // x is an instance of Container 

     } 
    } 
} 

:私は、これははるかに(その不必要に「あやふや」が、私と一緒に裸のように、私はこの例では、他のタイプのために取り扱いの多くをカットしました)得ていますlistから本質的にはList<t.GetType()>ですので、addメソッドにアクセスしてアイテムを追加できます。

答えて

19

System.Collections.IListにキャストして、直接Addメソッドを呼び出す必要があります。長所:シンプルで醜い反射はありません。短所:値の型を含むリストのボクシングを引き起こします。

+0

何をすべきかです。 –

17

私は本当に何かが欠けていない限り、これはうまくいくはずです。

ループの外

var add = type.GetMethod("Add"); 

ループ内

add.Invoke(list, new[] { item }); 
+0

これは良い答えです。私はあなたの応答を+1していただきありがとうございます。 bobbymcrの作品は、しかし反射を使用していないので、私はそれと一緒に行くつもりです。再度、感謝します。 –

1

あなたは正しいクローズジェネリック型を返します。これは、type.MakeGenericType(type.GetGenericArguments())を呼び出す必要があります。その後、反射的にAddメソッドを呼び出す必要があります。コードは次のようなものになります。

Type listType = type.MakeGenericType(type.GetGenericArguments()); 
    MethodInfo addMethod = listType.GetMethod("Add"); 
    addMethod.Invoke(instance, new object[] { ... }); 

を私はあなたがinstanceとして使用するかわからないんだけど、これはメソッドの呼び出しの対象となる実際オブジェクトです。

質問するのが良い質問は、なぜこれを行うことですか? .NET Frameworkには、すでにこの種の作業をすべて行う方法を知っているシリアライザが含まれています。あなたができるなら、あなたは "あなた自身のロール"をしようとする代わりに、それらの1つを使用する必要があります。

+0

私は誰かが "なぜ?" XmlSerializerにはいくつかの制限があります(特にリストはサポートされていません)。私が検討した他のオプションは、このプロジェクトではあまりにも冗長でした(これはフレームワークなので、少し下のレベルで動作すれば問題ありません) 。基本的に私が探しているシンプルさを達成するために、私は自分自身をロールバックする必要があります。 –

+0

@ John Sheehan:結果として得られるシリアル化されたデータは、あなたにとって重要なものですか? WCFデータコントラクティブシリアライザなど、XmlSerializerだけでなく他のシリアライザも使用できます。これは簡単に使用でき、 'List 'に対応しています。はい、それはいくつかの醜い探しているXMLを生成することができますが、一般的には問題ではありません。 –

+0

シリアライズは必要ありません。デシリアライズするだけで、属性を使用する必要はありません。 –

0

これは私が、私はそのアイデアのように

var genericType = _primaryType.GetGenericArguments().First(); 
    var type = typeof(List<>).MakeGenericType(genericType); 
    IList o = (IList)Activator.CreateInstance(type); 
    o.Add(x)