Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop through a class which contains variables

Tags:

c#

class

I would like to compare two classes that look like this

public class Order
{
        public string KundNummer, KundNamn, ErReferens, VarReferens, KontraktsNummer, Betvillk, Levvillk, Levsatt, Speditor,
            Resenh, Projekt, OrderDatum, LeveransDatum, ErtOrdernr, LagerbokfDatum, KundPostAdr, KundPostAdr2, KundGLN, KundPostnr, 
            KundOrt, KundLandKod, KundLand, KundVATnr, KundDistrikt, KundSaljare, KundText1, KundText2, KundText3, KundSprak,
            KundValuta, KundRabattAvtal, KundRabattAvtalBenamning, KundPrislista, KundPrislistaBenamning, KundALnamn, KundALpostAdr, KundALpostAdr2, KundALGLN, KundALpostnr, KundALort,
            KundALlandKod, KundALland;
        public double OrderNummer, Fakturarabatt, Frakt, Expavg, Brutto, Netto, ExklMoms, Totalt, Moms, Avrundn, KundValutaKurs, KundValutaEnhet;
        public int EUPeriodSamman, InklMoms, EjKlar, Levererad, Malukerad, BestallningSkapad, Ordererk,
            Plocklista, Foljesedel, ExtraOrderdokument, Restorder, Faktura, KundSparaText, KundExport, KundRantefakturering, KundKravbrev,
            KundKravavgift, KundRestnoteraEj, KundSamlingsfakturera;
    }

i want to compare two objects of this class for logging which fields in my database that changed.

public string OrderUppdateraOrder(Order order)
    {
        Order OrderToCompare = new Order();
        OrderToCompare = OrderVisaOrderInformation(order.OrderNummer);

        //then the code goes on to make the changes to the database from the class order
        //while OrdertoComapre still have the values from before this function was called
    }

So is it possible to loop through these classes and compare them or do I have to write an if for every variable in my class? :)

Or maybe convert it to a List? I don't know? :P

Thank you for answers

like image 862
Dendei Avatar asked Mar 10 '26 08:03

Dendei


2 Answers

i want to log if there is a difference and log the difference something like this CustomerNumber: changed from 456 to 345

The best option is probably just to use reflection to crawl over the public properties and fields, comparing them. This will have less code to compare, but will have a performance overhead. You can greatly reduce that overhead using tools like FastMember:

static class Program {
    static void Main()
    {
        Order o1 = new Order { Resenh = "abc" },
              o2 = new Order { Resenh = "abc" };
        ShowDiffs(o1, o2); // {nothing}
        o2.Resenh = "def";
        ShowDiffs(o1, o2); // Resenh changed from abc to def
    }
    static void ShowDiffs<T>(T x, T y)
    {
        var accessor = TypeAccessor.Create(typeof(T));
        if (!accessor.GetMembersSupported) throw new NotSupportedException();
        var members = accessor.GetMembers();

        foreach (var member in members)
        {
            object xVal = accessor[x, member.Name],
                   yVal = accessor[y, member.Name];
            if (!Equals(xVal, yVal))
            {
                Console.WriteLine("{0} changed from {1} to {2}",
                    member.Name, xVal, yVal);
            }
        }
    }
}
like image 174
Marc Gravell Avatar answered Mar 12 '26 21:03

Marc Gravell


Ok from how I understand you - you have a method which will retreive an Order object from the database and an Order object which you may have intially got from a database, but modified. You want to check if one, or many orders have change without saying:

For each order if Database.A equals Your.A etc.

I would put your check into one place and override the Equals method.

  public class Order
  {
    public int Id;
    public string SomeProp;
    public string AnotherProp;
    public override bool Equals(object obj)
    {
      Order orderToCompare = (Order)obj;
      return (SomeProp == orderToCompare.SomeProp && AnotherProp == orderToCompare.AnotherProp);
    }
  }

Then have two methods, one for updating a single order and one for updating many orders.

private void UpdateOrder(Order o)
{
  //Get the corresponding order from the database (I suspect Entity Framework here in order to get an object?)
  Order dbOrder = OrderVisaOrderInformation(o.Id);
  if (dbOrder.Equals(o))
  {
    //Do some update
  }
}
private void UpdateManyOrders(List<Order> orders)
{
  var dbOrders = (from order in orders
                  select OrderVisaOrderInformation(order.Id));
  List<Order> ordersToUpdate = dbOrders.Where(x => !x.Equals(orders.First(y => y.Id == x.Id))).ToList();
  foreach (Order orderToUpdate in ordersToUpdate)
  {
    //Update the order
  }
}

This may be wrong but from how I understand your question, this is what you want to do.

like image 39
LukeHennerley Avatar answered Mar 12 '26 20:03

LukeHennerley