Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting if-chain into rule-based dictionary

I'm stuck at converting a huge if-chain into a dictionary. In a legacy solution an Excel export is done like this:

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;

My idea is to split the rules and the actual row assigned off into 2 parts. So I've created a dictionary:

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

In order to get the current column value I do the following:

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;

The content of each cell in the finished report is now: System.Linq.Enumerable+WhereSelectEnumerableIterator2[System.Collections.Generic.KeyValuePair2[System.Func2[System.String,System.Boolean],System.Func2[System.Data.DataRow,System.Object]],System.Object] instead of its value.

What excactly am I doin wrong here?

like image 335
Marco Avatar asked Feb 14 '26 23:02

Marco


1 Answers

I suggest changing rules type:

// 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
};

And so

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);
}

Edit: in case of few complex rules (like "GF" one in the edited question) Dictionary<String, String> rule can also help out:

   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
       ...
     }
   }
like image 68
Dmitry Bychenko Avatar answered Feb 17 '26 12:02

Dmitry Bychenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!