Click here to Skip to main content
15,895,142 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hi Friends,

I need to write a generic method which will compare two objects of same type and stores all the mismatches in List<string>. My program flow is something like. I will post data via API call. Once i posted it will return me a unique ID of the post with the help of the ID i will call the GET method and de-serialize the response. I need to ensure that whatever i posted is am getting back so i need to compare POST object and GET object.
While comparing some of the properties should be ignored based upon the object i am passing to the method. Ignore list items i am reading from the config file.

What i tried, Loop through all the properties of the class using Reflection but i am not able to go inside of the list of objects. Please help me to modify the Compare method.

My sample class structure

C#
   class Plan
    {
        public  int planId { get; set; }
        public  string plnaName { get; set; }
        public  List<Client> clients { get; set; }
        public  List<Scenario> scenarios { get; set; }
        public  Setting settings { get; set; }
        public string verificationtimestamp { get; set; }
    }

    class Scenario
    {
        public  int scenarioId { get; set; }
        public  string scenarioName { get; set; }
        public  Liablity liablities { get; set; }
        public  Goal goals { get; set; }
        public  CashFlow cashflows { get; set; }
    }
    class Client
    {
        public int clientId { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        public string state { get; set; }
    }
    class Setting
    {
        public int analysishorizon { get; set; }
        public int iterations { get; set; }
        public Dictionary<string, string> settings { get; set; }
    }
    class Liablity
    {
        public  int liablityd { get; set; }
        public  string liablityName { get; set; }
    }
    class CashFlow
    {
        public  int cashflowId { get; set; }
        public  string cashflowName { get; set; }
    }
    class Goal
    {
        public  int goalId { get; set; }
        public  string goalName { get; set; }
    }
    enum Ignorelist
    {
        plan,
        planclient,
        scenario,
        goal,
        liabilities,
        cashflows
    }

What I have tried:
C#
public static List<String> lsterrorlogs = new List<string>();
      static void Main(string[] args)
      {
          Plan plnPost = new Plan
          {
              planId = 1,
              plnaName = "Plan1",
              scenarios = new List<Scenario>(){
                  new Scenario {scenarioId=1,scenarioName="scenario1",
                      liablities=new Liablity{liablityd=1,liablityName="L1"},
                      goals=new Goal{goalId=1,goalName="G1"},
                      cashflows=new CashFlow{cashflowId=1,cashflowName="CF1"}},
                  new Scenario {scenarioId=2,scenarioName="scenario2",
                      liablities=new Liablity{liablityd=2,liablityName="L2"},
                      goals=new Goal{goalId=2,goalName="G2"},
                      cashflows=new CashFlow{cashflowId=2,cashflowName="CF2"}}},
              settings = new Setting { analysishorizon = 10, iterations = 100 }
          };
          Plan plnGet = new Plan();
          plnGet = plnPost; //GetMethod()
          Compare<Plan>(plnPost, plnGet,Ignorelist.plan);
          Console.ReadLine();
      }

C#
static bool Compare<T>(T PostObject, T GetObject,Ignorelist il)
       {
           List<string> ignoreitems = new List<string>();
           switch (il)
           {
               case Ignorelist.plan:
                  // ignoreitems = GetIgnoreitems();
                   ignoreitems.Add("verificationtimestamp");
                   ignoreitems.Add("planId");
                   break;
               case Ignorelist.planclient:
                   break;
               case Ignorelist.scenario:
                   break;
               case Ignorelist.goal:
                   break;
               case Ignorelist.liabilities:
                   break;
               case Ignorelist.cashflows:
                   break;
               default:
                   break;
           }
           Type type = PostObject.GetType();
           foreach (PropertyInfo properties in type.GetProperties())
           {
                object valuePost;
               object valueGet;
               valuePost = GetPropValue(PostObject, properties.Name);
               valueGet = GetPropValue(GetObject, properties.Name);
               if (valuePost == null && valueGet != null || valuePost != null && valueGet == null)
                   lsterrorlogs.Add("one of the values is null");
           }

           return true;
       }
public static object GetPropValue(object src, string propName)
       {
           return src.GetType().GetProperty(propName).GetValue(src, null);
       }
Posted
Updated 8-Apr-16 14:27pm
v3
Comments
Sergey Alexandrovich Kryukov 8-Apr-16 16:55pm    
Okay, very nice, you can compare ignoring some properties. What's the problem?

Another aspect is quite delicate: how about identity? Do you need to use the objects in some associative container (notably Set or Dictionary)? In this case, it's important to correctly override GetHashCode (which is required if you override Equals, but not only in this case); in this case, it's easy to screw up identity of you ignore some properties. With this warning and understanding it, the problem is trivial.

—SA
BillWoodruff 8-Apr-16 17:21pm    
"i am not able to go inside of the list of objects"

What is the error message that occurs, and where does it occur ?

Have you considered having your classes implement IComparable, or IEquatable ?

There is a powerful open-source library available that offers the ability to specify properties to ignore:

https://github.com/GregFinzer/Compare-Net-Objects
jinesh sam 8-Apr-16 17:36pm    
I am not getting any error message.. but i am not aware how to identify particular property is List, for example in plan object 3rd property is List client. in this case i need to again loop through the client object and have a check
BillWoodruff 8-Apr-16 17:54pm    
"i need to again loop through the client object and have a check"

Yes, your comparison function must be either recursive, or call separate functions to evaluate objects with "depth" for each type: List, Dictionary, etc.

Why not implement IEquatable, or IComparable, for each Class ? Much better to avoid recursion, if possible.

Also, you can study Finzer's code at the site I showed you a link to.
jinesh sam 8-Apr-16 18:09pm    
Thanks :) Let me have a look on the Finzer's code

1 solution

I would serialize both objects to XML; using the "XmlIgnore" attribute to skip any properties that I did not want to compare.

I would then compare the XML (see below); or deserialize the "filtered" XML back and compare those instances.

The XML Diff and Patch GUI Tool[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900