O
orekinbck
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.PropertyType[] objectArray =
(propInfo.PropertyType[])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.Reflection;
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="leftObject"></param>
/// <param name="rightObject"></param>
/// <returns>True to indicate that the objects are equal.
False otherwise</returns>
public static bool AreTheseObjectEqual(Type thisType, object
leftObject, object rightObject)
{
if (leftObject == null && rightObject == null)
return true;
if (leftObject == null || rightObject == null)
return false;
PropertyInfo[] fields = thisType.GetProperties();
foreach (PropertyInfo propInfo in fields)
{
if (propInfo.PropertyType.IsArray)
{
//*********************************************************************************
//Property is an array, need to iterate through the
elements and compare them
//*********************************************************************************
//object lhs = propInfo.GetValue(leftObject, null);
//object rhs = propInfo.GetValue(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.Length != rhsArray.Length)
// return false;
//else
//{
// for (int i = 0; i < lhsArray.Length; i++)
// {
// if (false ==
AreTheseObjectEqual(propInfo.PropertyType,
(object)lhsArray,(object)rhsArray))
// return false;
// }
//}
//BUT .... If I knew the type then this would
work:
//STE.Model.SecurityRoles[] secRolesLHS =
(STE.Model.SecurityRoles[])lhs;
//STE.Model.SecurityRoles[] secRolesRHS =
(STE.Model.SecurityRoles[])rhs;
//But I don't know the type at run time
}
else
{
object lhs = propInfo.GetValue(leftObject, null);
object rhs = propInfo.GetValue(rightObject, null);
if (propInfo.PropertyType.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.PropertyType.GetProperties();
if (nestedFields.Length > 0)
{
if (false ==
AreTheseObjectEqual(propInfo.PropertyType,
propInfo.GetValue(leftObject, null), propInfo.GetValue(rightObject,
null)))
return false;
}
}
}
}
return true;
}
}
}
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.PropertyType[] objectArray =
(propInfo.PropertyType[])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.Reflection;
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="leftObject"></param>
/// <param name="rightObject"></param>
/// <returns>True to indicate that the objects are equal.
False otherwise</returns>
public static bool AreTheseObjectEqual(Type thisType, object
leftObject, object rightObject)
{
if (leftObject == null && rightObject == null)
return true;
if (leftObject == null || rightObject == null)
return false;
PropertyInfo[] fields = thisType.GetProperties();
foreach (PropertyInfo propInfo in fields)
{
if (propInfo.PropertyType.IsArray)
{
//*********************************************************************************
//Property is an array, need to iterate through the
elements and compare them
//*********************************************************************************
//object lhs = propInfo.GetValue(leftObject, null);
//object rhs = propInfo.GetValue(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.Length != rhsArray.Length)
// return false;
//else
//{
// for (int i = 0; i < lhsArray.Length; i++)
// {
// if (false ==
AreTheseObjectEqual(propInfo.PropertyType,
(object)lhsArray,(object)rhsArray))
// return false;
// }
//}
//BUT .... If I knew the type then this would
work:
//STE.Model.SecurityRoles[] secRolesLHS =
(STE.Model.SecurityRoles[])lhs;
//STE.Model.SecurityRoles[] secRolesRHS =
(STE.Model.SecurityRoles[])rhs;
//But I don't know the type at run time
}
else
{
object lhs = propInfo.GetValue(leftObject, null);
object rhs = propInfo.GetValue(rightObject, null);
if (propInfo.PropertyType.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.PropertyType.GetProperties();
if (nestedFields.Length > 0)
{
if (false ==
AreTheseObjectEqual(propInfo.PropertyType,
propInfo.GetValue(leftObject, null), propInfo.GetValue(rightObject,
null)))
return false;
}
}
}
}
return true;
}
}
}