Saman Parser
Saman Parser

Reputation: 148

Check two object, of unknown type, for equality, comparing all their fields

I need to define a method to compare two different objects of a same type. The type of objects is not specific. The objects may be a DLL type, so I can't override Equals method. I have to do this by reflection. This code works if all the members of objects are of primitive type. But it doesn't work when an object has a field that isn't primitive. How can I do it by reflection?

public bool Equals(object obj1, object obj2)
{
    List<FieldInfo> fieldInfos =  obj1.GetType().GetFields().ToList();
    return (fieldInfos.Select(fieldInfo => new {fieldInfo, type = fieldInfo.GetType()})
        .Where(@t => @t.type.IsPrimitive || @t.type == typeof(string) || @t.type == typeof(Decimal))
        .Select(@t => @t.fieldInfo)).All(fieldInfo => fieldInfo.GetValue(obj1).Equals(fieldInfo.GetValue(obj2)));
}

Upvotes: 4

Views: 1674

Answers (2)

Natechawin
Natechawin

Reputation: 316

I want the utility function to compare any 2 objects. All of the type I want to cover is

  1. Primitive Type
  2. Any class that Implement IEnumerable (Like Dict or List)
  3. Any Class

so I use generic and reflection to do so. I code it like this.

        public static bool CompareObjects<T>(T expectInput, T actualInput)
    {
        // If T is primitive type.
        if (typeof(T).IsPrimitive)
        {
            if (expectInput.Equals(actualInput))
            {
                return true;
            }

            return false;
        }

        if (expectInput is IEquatable<T>)
        {
            if (expectInput.Equals(actualInput))
            {
                return true;
            }

            return false;
        }

        if (expectInput is IComparable)
        {
            if (((IComparable)expectInput).CompareTo(actualInput) == 0)
            {
                return true;
            }

            return false;
        }

        // If T is implement IEnumerable.
        if (expectInput is IEnumerable)
        {
            var expectEnumerator = ((IEnumerable)expectInput).GetEnumerator();
            var actualEnumerator = ((IEnumerable)actualInput).GetEnumerator();

            var canGetExpectMember = expectEnumerator.MoveNext();
            var canGetActualMember = actualEnumerator.MoveNext();

            while (canGetExpectMember && canGetActualMember && true)
            {
                var currentType = expectEnumerator.Current.GetType();
                object isEqual = typeof(Utils).GetMethod("CompareObjects").MakeGenericMethod(currentType).Invoke(null, new object[] { expectEnumerator.Current, actualEnumerator.Current });

                if ((bool)isEqual == false)
                {
                    return false;
                }

                canGetExpectMember = expectEnumerator.MoveNext();
                canGetActualMember = actualEnumerator.MoveNext();
            }

            if (canGetExpectMember != canGetActualMember)
            {
                return false;
            }

            return true;
        }

        // If T is class.
        var properties = typeof(T).GetProperties();
        foreach (var property in properties)
        {
            var expectValue = typeof(T).GetProperty(property.Name).GetValue(expectInput);
            var actualValue = typeof(T).GetProperty(property.Name).GetValue(actualInput);

            if (expectValue == null || actualValue == null)
            {
                if (expectValue == null && actualValue == null)
                {
                    continue;
                }

                return false;
            }

            object isEqual = typeof(Utils).GetMethod("CompareObjects").MakeGenericMethod(property.PropertyType).Invoke(null, new object[] { expectValue, actualValue });

            if ((bool)isEqual == false)
            {
                return false;
            }
        }

        return true;
    }

Upvotes: 2

Micah Armantrout
Micah Armantrout

Reputation: 6971

I have recently been told about this lib that will do exactly what you are wanting

http://comparenetobjects.codeplex.com/releases/view/47978

Upvotes: 5

Related Questions