Macro sustitución en C#

Una de las características de Visual Foxpro (mi anterior lenguaje antes de .net) y del que todos los días me acuerdo cuando me peleo con .net, era la utilización de macro sustitución, esta permitía realizar cosas como la siguiente:

   1: FOR i = 1 TO 12

   2:    xcam = 'Formas_pago.poraplaza' + ALLTRIM(STR(i))

   3:    IF &xcam > 0

   4:    ENDIF

   5: ENDFOR

De esta forma utilizando el símbolo &, podía evaluar el contenido de los campos sin tener que escribirlos uno a uno y ahorrando líneas de código.

Por desgracia c# no posee esta característica con un uso tan sencillo, se pueden realizar aproximaciones compilando el código al vuelo con codedoom o similares, pero personalmente evitaria utilizar estas técnicas si no es absolutamente necesario.

Ya metidos en harina, estaba en .net transcribiendo un bloque de código desde Fox y claro el pequeño programa de arriba daba lugar a un programa similar a este:

   1: /// Carga la configuración dependiente de la forma de pago correspondiente

   2: if (!string.IsNullOrEmpty(cvc.Forma_pago))

   3: {

   4:     using (ManagerBI<Formas_pago> manager = new ManagerBI<Formas_pago>() )

   5:     {

   6:         if (manager.GetRecord(cvc.Forma_pago))

   7:         {

   8:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_1);

   9:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_2);

  10:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_3);

  11:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_4);

  12:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_5);

  13:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_6);

  14:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_7);

  15:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_8);

  16:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_9);

  17:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_10);

  18:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_11);

  19:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_12);

  20:  

  21:             cvc.DiasPagoAdd(manager.Data.Dia_pago_1);

  22:             cvc.DiasPagoAdd(manager.Data.Dia_pago_2);

  23:             cvc.DiasPagoAdd(manager.Data.Dia_pago_3);

  24:             cvc.DiasPagoAdd(manager.Data.Dia_pago_4);

  25:             cvc.DiasPagoAdd(manager.Data.Dia_pago_5);

  26:             cvc.DiasPagoAdd(manager.Data.Dia_pago_6);

  27:             cvc.DiasPagoAdd(manager.Data.Dia_pago_7);

  28:             cvc.DiasPagoAdd(manager.Data.Dia_pago_8);

  29:             cvc.DiasPagoAdd(manager.Data.Dia_pago_9);

  30:             cvc.DiasPagoAdd(manager.Data.Dia_pago_10);

  31:             cvc.DiasPagoAdd(manager.Data.Dia_pago_11);

  32:             cvc.DiasPagoAdd(manager.Data.Dia_pago_12);

  33:  

  34:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_1);

  35:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_2);

  36:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_3);

  37:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_4);

  38:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_5);

  39:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_6);

  40:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_7);

  41:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_8);

  42:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_9);

  43:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_10);

  44:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_11);

  45:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_12);

  46:         }

  47:     }

  48: }

Qué horror, 36 líneas para hacer lo mismo, pero imaginar que en lugar de 36 campos tuviéramos 100. Se me ocurrió la idea de usar reflection para poder evitar la escritura de tantas  líneas y resulto relativamente fácil, la solución es interesante y en casos similares os permitirá reducir en gran medida vuestro código. El rendimiento de reflexión apenas penalizará la aplicación.

   1: /// Carga la configuración dependiente de la forma de pago correspondiente

   2: if (!string.IsNullOrEmpty(cvc.Forma_pago))

   3: {

   4:     using (ManagerBI<Formas_pago> manager = new ManagerBI<Formas_pago>() )

   5:     {

   6:         if (manager.GetRecord(cvc.Forma_pago))

   7:         {

   8:             Type t = manager.Data.GetType();

   9:  

  10:             for (int i = 1; i < 12; i++)

  11:             {

  12:                 string contador = i.ToString().Trim();

  13:                 decimal porcentajeAplazamiento = (decimal)t.InvokeMember("Porcentaje_aplazamiento_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);

  14:                 cvc.PorcentajesAplazamientoAdd(porcentajeAplazamiento);

  15:                 byte diaPago = (byte)t.InvokeMember("Dia_pago_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);

  16:                 cvc.DiasPagoAdd(diaPago);

  17:                 Int16 diasAplazamiento = (Int16)t.InvokeMember("Dias_aplazamiento_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);

  18:                 cvc.DiasAplazamientoAdd(diasAplazamiento);

  19:             }

  20:         }

  21:     }

  22: }

Espero que os sirva.