2009-08-01 10 views
0

プロパティ名と一致するデータを区切り文字のファイルに書きたい場合は、C#objectdumperヘルプファイルのコードをコピーしましたが、すべて正常に機能しているようですが、それを使用するのに十分な反射があります。私が心配しているのは、誤った値が間違った列に置かれていることです。リフレクションを使用してデリミットファイルにクラスを保存する

Field1,Field2 
Val1,Val2 
Val1,Val2 
Val2,Val1 << Could this ever happen ? 

また、このコードは何を意味していますか?以下

f != null ? f.GetValue(this) : p.GetValue(this, null) 

コード:

public string returnRec(bool header, string delim) 
{ 
    string returnString = ""; 
    bool propWritten = false; 
    MemberInfo[] members = this.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance); 
    foreach (MemberInfo m in members) 
    { 
     FieldInfo f = m as FieldInfo; 
     PropertyInfo p = m as PropertyInfo; 
     if (f != null || p != null) 
     { 
      if (propWritten) 
      { 
       returnString += delim; 
      } 
      else 
      { 
       propWritten = true; 
      } 
      if (header) 
       returnString += m.Name; 
      else 
      { 
       Type t = f != null ? f.FieldType : p.PropertyType; 
       if (t.IsValueType || t == typeof(string)) 
       { 
        returnString += f != null ? f.GetValue(this) : p.GetValue(this, null); 
       } 
      } 
     } 
    } 
    return returnString; 
} 

答えて

0

@astanderと@Frederikは、基本的にあなたが特に声の質問や懸念に答えているが、私はたいと思います少し効率的なやり方で物事をすることを提案する。ファイルに書き込むオブジェクトインスタンスの数によっては、あなたが提示したメソッドが非常に効率が悪くなる可能性があります。それは不要なすべての反復でリフレクションを介してタイプと価値の情報を集めているからです。

あなたが探しているのは、タイプ情報を一度検索してから、プロパティとフィールドの値を取得するためにリフレクションのみを使用するものです。 (.NET 3.5)、

public static IEnumerable<string> ReturnRecs(IEnumerable items, bool returnHeader, string delimiter) 
{ 
    bool haveFoundMembers = false; 
    bool haveOutputHeader = false; 
    PropertyInfo[] properties = null; 
    FieldInfo[] fields = null; 
    foreach (var item in items) 
    { 
     if (!haveFoundMembers) 
     { 
      Type type = item.GetType(); 
      properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
       .Where(pi => pi.PropertyType.IsValueType || pi.PropertyType == typeof (string)).ToArray(); 
      fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance) 
       .Where(fi => fi.FieldType.IsValueType || fi.FieldType == typeof(string)).ToArray(); 
      haveFoundMembers = true; 
     } 
     if (!haveOutputHeader) 
     { 
      yield return String.Join(delimiter, properties.Select(pi => pi.Name) 
            .Concat(fields.Select(pi => pi.Name)).ToArray()); 
      haveOutputHeader = true; 
     } 
     yield return String.Join(delimiter, 
           properties.Select(pi => pi.GetValue(item, null).ToString()) 
            .Concat(fields.Select(fi => fi.GetValue(item).ToString())).ToArray()); 
    } 

上記のコードはしかこのために、GetPropertiesGetFields記録 --alsoのグループごとに一回を行い、明示的にあったような特性とフィールドをソートする必要はありません@ Frederikの提案。ただ、いくつかの考えを追加する

+0

ありがとう、おそらく秒を節約するだけですが、私はこれを使用します。 –

1

型T = F = nullを!? f.FieldType:p.PropertyType;

尋ねるがFである、あれば!= nullの後、f.FieldType他p.PropertyType

が@astanderはすでにあなたにType t = f != null ? f.FieldType : p.PropertyType;に答えを与えている

Type t; 
if (f != null) 
    t = f.FieldType; 
else 
    t = p.PropertyType; 
+0

1:良い答えを、私は私の外にそれを残し、私はこの例では、ハイパーディスクリプタを有効にしていないが、それはちょうどであることに注意してください。 –

+0

ありがとう、couldntはそれを見上げるために呼ばれたものを覚えています。 –

0

のように書くことができ、これは、インラインであります質問、私はそれを残します。値を正しい列に入れることについては、型のメンバを特定の順序でリストすることはできませんが、使用する前にリストを並べ替えることで保証できます(Linqを使用します)。

MemberInfo[] members = typeof(Item).GetMembers(BindingFlags.Public | BindingFlags.Instance); 
IEnumerable<MemberInfo> sortedMembers = members.OrderBy(m => m.Name); 
foreach (MemberInfo member in sortedMembers) 
{ 
    // write info to file 
} 

それとも、非LINQのアプローチを好む場合(.NET Frameworkの2.0で動作しますが):

MemberInfo[] members = typeof(Item).GetMembers(BindingFlags.Public | BindingFlags.Instance); 
Array.Sort(members, delegate(MemberInfo x, MemberInfo y){ 
    return x.Name.CompareTo(y.Name); 
}); 

foreach (MemberInfo member in members) 
{ 
    // write info to file 
} 
+0

GetMembersが返品する注文の「証明」を探していましたが、何もわかりませんでした。だから私は上記のアプローチに同意する –

+0

それをありがとう、ありがとう、私の心を置きます。 –

0

は、大量のデータのために、特に、受け入れ答えを再:

  • PropertyInfoなどが不必要に遅くなることがあります。例えば、これを回避する方法、HyperDescriptorまたは他の動的コード
  • を使用してではなく、中間文字列の多くを構築するがあり、採用微調整バージョンとしてTextWriter

に直接出力を書き込むために、より効率的であり得ますこれらのアプローチは、以下を参照してください。

HyperTypeDescriptionProvider.Add(typeof(YourType)); 

とにかく...

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.IO; 
static class Program { 
    static void Main() { // just some test data... 
     var data = new[] { new { Foo = "abc", Bar = 123 }, new { Foo = "def", Bar = 456 } }; 
     Write(data, Console.Out, true, "|"); 
    } 
    public static void Write<T>(IEnumerable<T> items, TextWriter output, bool writeHeaders, string delimiter) { 
     PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); 
     foreach (T item in items) { 
      bool firstCol = true; 
      if (writeHeaders) {     
       foreach (PropertyDescriptor prop in properties) { 
        if (firstCol) { 
         firstCol = false; 
        } else { 
         output.Write(delimiter); 
        } 
        output.Write(prop.Name);      
       } 
       output.WriteLine(); 
       writeHeaders = false; 
       firstCol = true; 
      } 
      foreach (PropertyDescriptor prop in properties) { 
       if (firstCol) { 
        firstCol = false; 
       } else { 
        output.Write(delimiter); 
       } 
       output.Write(prop.Converter.ConvertToString(prop.GetValue(item))); 
      } 
      output.WriteLine(); 
     } 
    } 
} 
関連する問題