2012-04-04 13 views
0

質問:私はSystem.Reflection、フィールドとプロパティの位置を取得する方法?

MyConvertToを使用してデータテーブルにList<MyCsvFileType>を変換後

List<MyCsvFileType>

にcsvファイルをシリアル化するには、以下のクラスを使用し

(下記も同様)。 問題は、MyConvertToが列の位置を変更することです。つまり、すべてのプロパティはすべてpublic変数の後に になります。

この問題の原因は、後で私はSqlBulkCopyを使用して、DataTableをデータベーステーブルにコピーすることです。 残念ながら、SqlBulkCopyは、データベーステーブルへのデータ変換可能なオートマチック の列名ではなく、列のインデックスを使用します。それは(私のデータベース・テーブルは、クラスと同じレイアウトを持っているので)フロートエリアフィールドに英数字AP_FL_CADKey を挿入しようとするため、私は素敵なエラーメッセージを得ることを意味

...

は、どのような方法がありますMyConvertToのフィールド&の位置を取得できますか? データベーステーブル(ロット)を変更したり、BulkCopyの独自の実装( )を作成する必要はありません。手動でもデータテーブルとデータベーステーブルの間のマッピングを設定したくないからですか?

それはフィールドオフセットによってソートすることにより、最悪の場合には、可能なはず...

クラス:

[FileHelpers.IgnoreFirst] 
[FileHelpers.IgnoreEmptyLines] 
public class MyCsvFileType 
{ 
    public string FL_CADKey; 
    public string FL_DWG; 
    public string FL_ObjID; 

    public string FL_Area; 

    public double FL_Area_double 
    { 
     get 
     { 
      if (string.IsNullOrEmpty(this.FL_Area)) 
       return 0.0; 
      else 
       return System.Convert.ToDouble(this.FL_Area); 
     } 

    } // End Property PP_Area_double 


    public string AP_FL_CADKey; 


    public System.Guid UID 
    { 

     get 
     { 
      return System.Guid.NewGuid(); 
     } 

    } // End Property UID 
} 

MyConvertTo:

public static DataTable MyConvertTo(dynamic custs) 
{ 
    DataTable dt = MyCreateTable(custs); 

    System.Data.DataRow dr = null; 
    foreach (dynamic cli in custs) 
    { 
     Console.WriteLine(); 

     Type t = cli.GetType(); 

     dr = dt.NewRow(); 

     foreach (System.Reflection.FieldInfo fi in t.GetFields()) 
     { 
      dr[fi.Name] = fi.GetValue(cli); 
     } 

     foreach (System.Reflection.PropertyInfo pi in t.GetProperties()) 
     { 
      dr[pi.Name] = pi.GetValue(cli, null); 
     } 

     dt.Rows.Add(dr); 
    } // Next cli 

    return dt; 
} 



public static DataTable MyCreateTable(dynamic custs) 
    { 
     DataTable table = new DataTable("Table_1"); 

     foreach (dynamic cli in custs) 
     { 
      Console.WriteLine(); 

      Type t = cli.GetType(); 

      foreach (System.Reflection.FieldInfo fi in t.GetFields()) 
      { 
       table.Columns.Add(fi.Name, fi.FieldType); 
       //Console.WriteLine(fi.Name + ": " + fi.GetValue(cli)); 
      } 

      foreach (System.Reflection.PropertyInfo pi in t.GetProperties()) 
      { 
       table.Columns.Add(pi.Name, pi.PropertyType); 
       //Console.WriteLine(pi.Name + ": " + pi.GetValue(cli, null)); 
      } 

      break; 
     } // Next cli 

     return table; 
    } 
+0

いいえ、PositionAttribute(Position = 1)などの属性を作成することができます –

+0

@Adrian Iftode:Argh、私はむしろ独自のシリアライザを作成したいと思います。 –

+0

ほとんどのシリアライザは、属性ベースのシリアライゼーションを使用して、プロパティ、クラスについてのメタデータを取得します。 –

答えて

0

フィールドの順序返されるは同じであることが保証されていませんが、通常は定義された順序です。

私は、一貫性のある方法で返された配列を並べ替えるためにLinqを使用し、変換を使用することをお勧めします。

+0

[System.Runtime.InteropServices.StayLayout(System.Runtime.InteropServices.Layo utKind.Sequential)経費 ":) –

+0

はい、私はそれを認識しています。しかし、私は別のSOの質問にそれに問題があることを覚えています。そして、それはジョン・スカートのようなものでした。だから私は保証されていないと言った。 – Aliostad

+0

@Quandary私の解決策はシンプルで実用的なものだと思います。 – Aliostad

0

SqlBulkCopyインスタンスにColumnMappingsを設定するだけではなく、列名に基づいてIDマッピングを追加できますか?

データソースとデスティネーションテーブルは同じ数の列を有し、データ・ソース内の各ソース列の順序位置に対応する宛先列の順序位置と一致し、にColumnMappingsコレクションが不要な場合。ただし、列数が異なる場合、または順序の位置が一致しない場合は、ColumnMappingsを使用して、データが正しい列にコピーされていることを確認する必要があります。

など。各列を追加するときは、.Add(ColumnName,ColumnName)を呼び出してください。

+0

私はどこでもBulkCopyに同じクラスを使用しているので、大変です。これはいたるところで望ましい動作ではないかもしれません。 –

関連する問題