viernes, 6 de septiembre de 2013

Reflexión en C# : comparar campos de dos objetos utilizando LINQ


Un ejemplo de reflexión en C# utilizando LINQ. En el caso que se expone se crea la función fieldValuesDiff, que lo que hace es dados dos objetos, que pueden ser de distinto tipo, para todos aquellos campos con el mismo nombre y valor distinto, devuelve un IEnumerable<stObjDif>, es decir una lista de una estructura con el nombre del campo y los dos valores.

En particular yo lo he aplicado para hacer un log de campos modificados. Dados dos entitades de tipo A, le paso por parámetro una instancia de la entidad antes de modificar y otra modificada. Así puedo guardar el log.  

No obstante  se pueden añadir o cambiar fácilmente funciones basadas en esta, por ejemplo la función fieldsValuesEqual, para extraer campos iguales.

public class Reflection
{
    public struct stObjDif
    {
      public string Campo;
      public string ValorObj1;
      public string ValorObj2;
    }

    public List fieldsValuesDiff(object obj1, object obj2)
    {
      Type tOb1 = obj1.GetType();
      Type tOb2 = obj2.GetType();

      var listPropOrig = tOb1.GetProperties().Select(p => p).ToList();
      var listPropMod = tOb2.GetProperties().Select(p => p).ToList();

      return listPropMod.Where(pM =>
              listPropOrig.Count(pO => (pO.Name == pM.Name && pO.GetValue(obj1)!=null && pM.GetValue(obj2)!=null
                              && pO.GetValue(obj1).ToString() != pM.GetValue(obj2).ToString())) == 1
               ).Select(pResult => new stObjDif(){
                     Campo = pResult.Name,
                     ValorObj1 = pResult.GetValue(obj1).ToString(),
                     ValorObj2 = listPropMod.FirstOrDefault(pM => pM.Name == pResult.Name).GetValue(obj2).ToString()
                 }).ToList();
    }

1 comentario:

  1. hola una pregunta en la estrutra hay que colocar la estructura de los objetos o es generico estoy intentando entender un poco la estructura de la clase

    ResponderEliminar