2011-02-25 9 views
6

私はこのような印刷方法を持っている、のは、言ってみましょう:未知のコレクションの値を反復して印刷する一般的な方法はありますか?

private static void Print(IEnumerable items) 
{ 
    // Print logic here 
} 

私はテーブルのようなすべてのフィールドを印刷する必要があり、この印刷方法にコレクションクラスを渡したいです。たとえば、私の入力コレクションは「Persons」や「Orders」や「Cars」などです。

"Cars"コレクションをPrintメソッドに渡すと、次のような "Car"の詳細のリストが出力されます。 :Make、Color、Price、Class etc.

私は実行時までコレクションの種類を知りません。私は、TypeDescriptorsPropertyDescriptorCollectionを使って解決を試みました。しかし、私はそれが良い解決策であるとは思わない。表現やジェネリックを使ってこれを達成する他の方法はありますか?

+1

あなたがジェネリックにできる最善についてのすべてが(ToStringメソッドを直接オーバーライドされていないと仮定して)いくつかの 'IMyToString'インタフェースを実装していて、 'IEnumerable 'をとります。他の方法もありますが、一般的にマッピング(TypeConvertersはマッピングの一種です)に依存するか、RTTIを他の方法で利用します。 –

答えて

6

あなたは、このような印刷を実現することができプロパティ。

私はここでジェネリックスを使うべきだと主張します(他の回答の提案とは対照的に)。テーブルヘッダーを印刷できるように、コレクション内のアイテムを単一の型にする必要があります。

テーブルの書式設定では、this questionの回答を確認できます。

+0

まさに私が探していたものです。多くのおかげで:) –

+0

これは私が探しているもので、 'Object'のプロパティ名を一度印刷し、リストの各項目の値を印刷するためのものです。ありがとう! – Shiva

7

オブジェクトのToString()メソッドをオーバーライドして、表示したいすべての情報を組み込み、好きなときに呼び出します。表現やジェネリックの必要はありません。

+1

+1標準多型パターンを示唆しています。クラスが封印されている場合は、「ビジターパターン」(冗長な逆パターン一致;-)を使用できます。 –

+0

そして.netのvisitorパターンは拡張メソッドだけです。 – Pradeep

+0

上記の解決策は本当に良いです。しかし、別の問題があります。たとえば、p> ID = o.PersonIDのOrdersのPersons join oからvar result = select pのようなunknowコレクションを渡すと、新しい{p.Name、o.Name}を選択すると、「 'Print(結果); 'この場合、どのようにこれを達成できますか? –

3

タイプがわからない場合は、リフレクションを使用することをおすすめします。それは良い解決策です。なぜあなたはそれが良い解決策ではないと感じますか?それは単に、プロパティの名前を印刷するには、クラスの各プロパティをループし、各項目の上に印刷し、各項目について、それはの値を出力

static void Print<T>(IEnumerable<T> items) 
{ 
    var props = typeof(T).GetProperties(); 

    foreach (var prop in props) 
    { 
     Console.Write("{0}\t", prop.Name); 
    } 
    Console.WriteLine(); 

    foreach (var item in items) 
    { 
     foreach (var prop in props) 
     { 
      Console.Write("{0}\t", prop.GetValue(item, null)); 
     } 
     Console.WriteLine(); 
    } 
} 

1

この例では、式を使用してパフォーマンスのためにあなたのための印刷方法をキャッシュ:

class MyObject 
    { 
     public int Property1 { get; set;} 
     public string Property2 { get; set; } 
    } 
    class MyOtherObject 
    { 
     public int Property3 { get; set; } 
     public string Property4 { get; set; } 
    } 
    static void Main(string[] args) 
    { 
     Array.ForEach(new[] 
     { 
      new MyObject { Property1 = 1, Property2 = "P" }, 
      new MyObject { Property1 = 2, Property2 = "Q" } 
     }, Print); 
     Array.ForEach(new[] 
     { 
      new MyOtherObject { Property3 = 3, Property4 = "R" }, 
      new MyOtherObject { Property3 = 4, Property4 = "S" } 
     }, Print); 
     Console.ReadKey(); 
    } 
    static void Print<T>(T item) 
    { 
     ObjectPrinter<T>.PrintAction(item, Console.Out); 
    } 
    static class ObjectPrinter<T> 
    { 
     public static readonly Action<T, TextWriter> PrintAction = CreatePrintAction(); 
     private static Action<T, TextWriter> CreatePrintAction() 
     { 
      ParameterExpression item = Expression.Parameter(typeof(T), "item"); 
      ParameterExpression writer = Expression.Parameter(typeof(TextWriter), "writer"); 
      var writeLineMethod = typeof(TextWriter).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string) }, null); 
      var concatMethod = typeof(string).GetMethod("Concat", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object), typeof(object) }, null); 
      var writeDashedLine = Expression.Call(
       writer, 
       writeLineMethod, 
       Expression.Constant(
        new String('-', 50) 
       ) 
      ); 
      var lambda = Expression.Lambda<Action<T, TextWriter>>(
       Expression.Block(
        writeDashedLine, 
        Expression.Block(
         from property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) 
         where property.GetGetMethod().GetParameters().Length == 0 
         select Expression.Call(
          writer, 
          writeLineMethod, 
          Expression.Call(
           null, 
           concatMethod, 
           Expression.Constant(
            property.Name + ":" 
           ), 
           Expression.Convert(
            Expression.Property(
             item, 
             property 
            ), 
            typeof(object) 
           ) 
          ) 
         ) 
        ), 
        writeDashedLine 
       ), 
       item, 
       writer 
      ); 
      return lambda.Compile(); 
     } 
    } 
関連する問題