A Function That Compares the Properties of Two Objects

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • orekinbck@yahoo.com.au

    A Function That Compares the Properties of Two Objects

    Hi There

    I am learning about reflection so apologies if this post is vague ...

    I am doing some unit testing and have written a function that accepts
    two objects and tests to see if their properties are equal. It seems
    to work OK except when a object has a property that is an array.

    The GetValue method of the PropertyInfo class returns an object, and I
    want to convert it to an array of objects. For some reason, this
    fails:

    object[] objectArray = (object[])myObject;

    However if I know the type, then it works. For example:

    SecurityRoles[] rolesArray = (SecurityRoles[])object;

    The problem is that I don't know the type at design time ! I tried to
    do this:

    propInfo.Proper tyType[] objectArray =
    (propInfo.Prope rtyType[])myObject;

    But it did not compile (ps ... propInfo is an instance of the
    PropertyInfo class).

    The code listing for my function is below. I would really appreciate
    any guidance!

    Thanks
    Bill

    using System;
    using System.Reflecti on;

    namespace ServerTest
    {
    public static class ObjectComparer
    {
    /// <summary>
    /// This function compares any two objects properties. It will
    recursively search down through nested properties
    /// WARNING - It only compares properties that are one of the
    following string, char, short, int, long, bool, DateTime, Enum
    /// *** IT IGNORES ANY PROPERTIES THAT ARE ARRAYS ***
    /// </summary>
    /// <param name="thisType" >The type of the two objects</param>
    /// <param name="leftObjec t"></param>
    /// <param name="rightObje ct"></param>
    /// <returns>True to indicate that the objects are equal.
    False otherwise</returns>
    public static bool AreTheseObjectE qual(Type thisType, object
    leftObject, object rightObject)
    {
    if (leftObject == null && rightObject == null)
    return true;

    if (leftObject == null || rightObject == null)
    return false;

    PropertyInfo[] fields = thisType.GetPro perties();

    foreach (PropertyInfo propInfo in fields)
    {
    if (propInfo.Prope rtyType.IsArray )
    {


    //*************** *************** *************** *************** *************** ******
    //Property is an array, need to iterate through the
    elements and compare them

    //*************** *************** *************** *************** *************** ******

    //object lhs = propInfo.GetVal ue(leftObject, null);
    //object rhs = propInfo.GetVal ue(rightObject,
    null);

    ////This does not work
    //object[] lhsArray = (object[])lhs;
    //object[] rhsArray = (object[])rhs;

    ////If the above worked, I could then do this:
    //if (lhsArray.Lengt h != rhsArray.Length )
    // return false;
    //else
    //{
    // for (int i = 0; i < lhsArray.Length ; i++)
    // {
    // if (false ==
    AreTheseObjectE qual(propInfo.P ropertyType,
    (object)lhsArra y[i],(object)rhsArr ay[i]))
    // return false;
    // }
    //}

    //BUT .... If I knew the type then this would
    work:
    //STE.Model.Secur ityRoles[] secRolesLHS =
    (STE.Model.Secu rityRoles[])lhs;
    //STE.Model.Secur ityRoles[] secRolesRHS =
    (STE.Model.Secu rityRoles[])rhs;
    //But I don't know the type at run time
    }
    else
    {
    object lhs = propInfo.GetVal ue(leftObject, null);
    object rhs = propInfo.GetVal ue(rightObject, null);

    if (propInfo.Prope rtyType.IsEnum)
    {
    if (lhs.ToString() != rhs.ToString())
    return false;
    }
    else if (lhs is string)
    {
    if (false == rhs is string)
    return false;
    if ((string)lhs != (string)rhs)
    return false;
    }
    else if (lhs is char)
    {
    if (false == rhs is char)
    return false;
    if ((char)lhs != (char)rhs)
    return false;
    }
    else if (lhs is bool)
    {
    if (false == rhs is bool)
    return false;
    if ((bool)lhs != (bool)rhs)
    return false;
    }
    else if (lhs is short)
    {
    if (false == rhs is short)
    return false;
    if ((long)lhs != (long)rhs)
    return false;
    }
    else if (lhs is int)
    {
    if (false == rhs is int)
    return false;
    if ((int)lhs != (int)rhs)
    return false;
    }
    else if (lhs is long)
    {
    if (false == rhs is long)
    return false;
    if ((long)lhs != (long)rhs)
    return false;
    }
    else if (lhs is DateTime)
    {
    if (false == rhs is DateTime)
    return false;
    if ((DateTime)lhs != (DateTime)rhs)
    return false;
    }
    else
    {
    PropertyInfo[] nestedFields =
    propInfo.Proper tyType.GetPrope rties();
    if (nestedFields.L ength > 0)
    {
    if (false ==
    AreTheseObjectE qual(propInfo.P ropertyType,
    propInfo.GetVal ue(leftObject, null), propInfo.GetVal ue(rightObject,
    null)))
    return false;
    }
    }
    }
    }
    return true;
    }
    }
    }

  • Ashura

    #2
    RE: A Function That Compares the Properties of Two Objects

    Thats not so hard to do:

    //...

    PropertyInfo[] fields = thisType.GetPro perties();
    foreach (PropertyInfo propInfo in fields) {

    if (propInfo.Prope rtyType.IsArray ) {
    object val = propInfo.GetVal ue(angel, null);

    IEnumerator ie = ((System.Array) val).GetEnumera tor();
    while(ie.MoveNe xt()) {
    //Now we have the individual object in the array
    Console.WriteLi ne(ie.Current.G etType().ToStri ng());
    }
    }

    //...
    }

    Comment

    • Ignacio Machin \( .NET/ C# MVP \)

      #3
      Re: A Function That Compares the Properties of Two Objects

      Hi,


      Ashura's post should solve your problem, I just want to remember you that if
      a property has a reference type you are comparing references ( if both
      instances refers to the very same instance, not two instances with same
      values).


      cheers,

      --
      Ignacio Machin,
      ignacio.machin AT dot.state.fl.us
      Florida Department Of Transportation



      <orekinbck@yaho o.com.au> wrote in message
      news:1131094226 .727025.317640@ g49g2000cwa.goo glegroups.com.. .[color=blue]
      > Hi There
      >
      > I am learning about reflection so apologies if this post is vague ...
      >
      > I am doing some unit testing and have written a function that accepts
      > two objects and tests to see if their properties are equal. It seems
      > to work OK except when a object has a property that is an array.
      >
      > The GetValue method of the PropertyInfo class returns an object, and I
      > want to convert it to an array of objects. For some reason, this
      > fails:
      >
      > object[] objectArray = (object[])myObject;
      >
      > However if I know the type, then it works. For example:
      >
      > SecurityRoles[] rolesArray = (SecurityRoles[])object;
      >
      > The problem is that I don't know the type at design time ! I tried to
      > do this:
      >
      > propInfo.Proper tyType[] objectArray =
      > (propInfo.Prope rtyType[])myObject;
      >
      > But it did not compile (ps ... propInfo is an instance of the
      > PropertyInfo class).
      >
      > The code listing for my function is below. I would really appreciate
      > any guidance!
      >
      > Thanks
      > Bill
      >
      > using System;
      > using System.Reflecti on;
      >
      > namespace ServerTest
      > {
      > public static class ObjectComparer
      > {
      > /// <summary>
      > /// This function compares any two objects properties. It will
      > recursively search down through nested properties
      > /// WARNING - It only compares properties that are one of the
      > following string, char, short, int, long, bool, DateTime, Enum
      > /// *** IT IGNORES ANY PROPERTIES THAT ARE ARRAYS ***
      > /// </summary>
      > /// <param name="thisType" >The type of the two objects</param>
      > /// <param name="leftObjec t"></param>
      > /// <param name="rightObje ct"></param>
      > /// <returns>True to indicate that the objects are equal.
      > False otherwise</returns>
      > public static bool AreTheseObjectE qual(Type thisType, object
      > leftObject, object rightObject)
      > {
      > if (leftObject == null && rightObject == null)
      > return true;
      >
      > if (leftObject == null || rightObject == null)
      > return false;
      >
      > PropertyInfo[] fields = thisType.GetPro perties();
      >
      > foreach (PropertyInfo propInfo in fields)
      > {
      > if (propInfo.Prope rtyType.IsArray )
      > {
      >
      >
      > //*************** *************** *************** *************** *************** ******
      > //Property is an array, need to iterate through the
      > elements and compare them
      >
      > //*************** *************** *************** *************** *************** ******
      >
      > //object lhs = propInfo.GetVal ue(leftObject, null);
      > //object rhs = propInfo.GetVal ue(rightObject,
      > null);
      >
      > ////This does not work
      > //object[] lhsArray = (object[])lhs;
      > //object[] rhsArray = (object[])rhs;
      >
      > ////If the above worked, I could then do this:
      > //if (lhsArray.Lengt h != rhsArray.Length )
      > // return false;
      > //else
      > //{
      > // for (int i = 0; i < lhsArray.Length ; i++)
      > // {
      > // if (false ==
      > AreTheseObjectE qual(propInfo.P ropertyType,
      > (object)lhsArra y[i],(object)rhsArr ay[i]))
      > // return false;
      > // }
      > //}
      >
      > //BUT .... If I knew the type then this would
      > work:
      > //STE.Model.Secur ityRoles[] secRolesLHS =
      > (STE.Model.Secu rityRoles[])lhs;
      > //STE.Model.Secur ityRoles[] secRolesRHS =
      > (STE.Model.Secu rityRoles[])rhs;
      > //But I don't know the type at run time
      > }
      > else
      > {
      > object lhs = propInfo.GetVal ue(leftObject, null);
      > object rhs = propInfo.GetVal ue(rightObject, null);
      >
      > if (propInfo.Prope rtyType.IsEnum)
      > {
      > if (lhs.ToString() != rhs.ToString())
      > return false;
      > }
      > else if (lhs is string)
      > {
      > if (false == rhs is string)
      > return false;
      > if ((string)lhs != (string)rhs)
      > return false;
      > }
      > else if (lhs is char)
      > {
      > if (false == rhs is char)
      > return false;
      > if ((char)lhs != (char)rhs)
      > return false;
      > }
      > else if (lhs is bool)
      > {
      > if (false == rhs is bool)
      > return false;
      > if ((bool)lhs != (bool)rhs)
      > return false;
      > }
      > else if (lhs is short)
      > {
      > if (false == rhs is short)
      > return false;
      > if ((long)lhs != (long)rhs)
      > return false;
      > }
      > else if (lhs is int)
      > {
      > if (false == rhs is int)
      > return false;
      > if ((int)lhs != (int)rhs)
      > return false;
      > }
      > else if (lhs is long)
      > {
      > if (false == rhs is long)
      > return false;
      > if ((long)lhs != (long)rhs)
      > return false;
      > }
      > else if (lhs is DateTime)
      > {
      > if (false == rhs is DateTime)
      > return false;
      > if ((DateTime)lhs != (DateTime)rhs)
      > return false;
      > }
      > else
      > {
      > PropertyInfo[] nestedFields =
      > propInfo.Proper tyType.GetPrope rties();
      > if (nestedFields.L ength > 0)
      > {
      > if (false ==
      > AreTheseObjectE qual(propInfo.P ropertyType,
      > propInfo.GetVal ue(leftObject, null), propInfo.GetVal ue(rightObject,
      > null)))
      > return false;
      > }
      > }
      > }
      > }
      > return true;
      > }
      > }
      > }
      >[/color]


      Comment

      • S. Senthil Kumar

        #4
        Re: A Function That Compares the Properties of Two Objects

        Unless of course, the reference type overloaded the equality operator.

        Comment

        • Ben

          #5
          Re: A Function That Compares the Properties of Two Objects

          Great !!! It appears to be working perfectly. Thanks everyone for your help.

          If you are interested I have posted the complete code:



          It is my first foray into reflection and recursion, so I would be interested
          in any feedback

          Cheers
          Bill

          Comment

          Working...