2016-04-29 17 views
2

私は巨大なif-chainを辞書に変換することに専念しています。従来のソリューションでは、Excelのエクスポートは次のように行われます。if-chainをルールベースの辞書に変換する

foreach (DataRow dr in fullData.Rows) 
{ 
    DataRow newRow = dt.NewRow(); 

    foreach (DataColumn dc in dt.Columns) 
    { 
     String s = dc.Caption; 

     if (s.Equals("ID")) 
      newRow[dc] = dr["id"]; 
     else if (s.Equals("PQ-Nr")) 
      newRow[dc] = dr["pqNummer"]; 
     else if (s.Equals("GJ")) 
      newRow[dc] = dr["geschaeftsjahr"]; 
     else if (s.Equals("Link")) 
      newRow[dc] = dr["link"]; 
     /*more complex example*/ 
     else if(s.Equals("GF")) 
     { 
      string content = ""; 
      int intVal = 0; 
      if (Int32.TryParse(dr["id"].ToString(), out intVal)) 
      { 
       List<Freigabe> liste = DBHelper.getFreigabenByPersonalTyp(intVal, Personal.GF); 
       foreach (Freigabe f in liste) 
       { 
       //build content string here 
       } 
      } 
      newRow[dc] = content.TrimEnd(); 
     } 
     /*plus around 60 more else if statements*/ 
    } 
    dt.Rows.Add(newRow); 
} 
return dt; 

私の考えは、ルールと2つの部分に割り当てられた実際の行を分割することです。だから私は辞書を作成しました:

var rules = new Dictionary<Func<string, bool>, Func<DataRow, object>>() 
{ 
    {y => y == "ID", x => x["id"] }, 
    {y => y == "PQ-Nr", x => x["pqNummer"] }, 
    //.... 
}; 

現在の列の値を取得するために、私は次のようにします。

foreach (DataRow dr in fullData.Rows) 
{ 
    DataRow newRow = dt.NewRow(); 

    foreach (DataColumn dc in dt.Columns) 
    { 
     String s = dc.Caption; 

     newRow[dc] = from r in rules 
        where r.Key(s) 
        select r.Value(dr); 
    } 
    dt.Rows.Add(newRow); 
} 
return dt; 

を完成したレポートの各セルの内容は以下のようになります。System.Linq.Enumerable+WhereSelectEnumerableIterator 2 [ System.Collections.Generic.KeyValuePair 2[System.Func 2 [System.String、System.Boolean]、System.Func 2[System.Data.DataRow,System.Object]],System.Object]の代わりに値です。

私はここで間違っていますか?

+3

あなたのlinqの部分は、r.Key(s)がr.Value(dr);を選択するルール内のrから、複数の値を返すことができます。結果を1に制限してください。 –

+0

ああああ。私は今、テーブルに頭を打ちつけるのに足りない。これを回答として追加したいですか? – Marco

答えて

4
rules.Where(r => r.Key(s)). 
    Select(r => r.Value(dr)). 
    FirstOrDefault(); // Should do the trick. 
5

私はrulesタイプ変更することをお勧め:

// No lambdas, just string to string 
Dictionary<String, String> rules = new Dictionary<String, String>() { 
    {"ID", "id"}, 
    {"PQ-Nr", "pqNumme"}, 
    {"GJ", "geschaeftsjahr"}, 
    {"Link", "link"}, 
    //TODO: put other rules here 
}; 

としそう

foreach (DataRow dr in fullData.Rows) { 
    DataRow newRow = dt.NewRow(); 

    foreach (DataColumn dc in dt.Columns) 
     newRow[dc] = dr[rules[dc.Caption]]; 

    dt.Rows.Add(newRow); 
} 

編集少数の複雑なルール(のような、編集された問題の"GF" 1)の場合、 Dictionary<String, String> ruleもお手伝いできます:

foreach (DataColumn dc in dt.Columns) { 
    String rule; 

    if (rules.TryGetValue(dc.Caption, out rule)) 
     newRow[dc] = dr[rule]; // <- all the simple rules 
    else if (dc.Caption.Equals("GF")) { // <- few specific rules 
     ... 
    } 
    } 
+0

私は遅く書く: – Grundy

+0

これは本来の目的ではありませんが、文字列を返す前にFuncにいくつかのロジックを追加する必要があるため、目的に合わないものです。私はちょうどポイントを作るために私の例でそれを単純に保った – Marco

+0

@Serv:私は参照してください。ロジックがここでは重要だと思われるので、いくつかの例を挙げてください。 –

関連する問題