lundi 27 février 2017

Generic comparer using reflection

I am putting together simple generic comparer for unit testing.
I don't want to use IComparable interface because there is just too much classes that would need to implement it, and it will be only used in Unit tests so performance of reflection is not an issue.

So far I have this:

 public IEnumerable<NonEqualProperty> Compare<T>(T first, T second) where T : class
        {
            var list = new List<NonEqualProperty>();
            var type = first.GetType();
            var properties = type.GetProperties();

            var basicTypes = properties.Where(p => !p.PropertyType.IsClass && !p.PropertyType.IsInterface
                                                   || p.PropertyType == typeof(string));


            foreach (var prop in basicTypes)
            {
                var value1 = prop.GetValue(first, null);
                var value2 = prop.GetValue(second, null);

                if (value1 != null && value2 != null && value1.Equals(value2) || value1 == null && value2 == null )
                    continue;

                list.Add(new NonEqualProperty(prop.Name, value1, value2));
            }

            var enumerableTypes =
                from prop in properties
                from interfaceType in prop.PropertyType.GetInterfaces()
                where interfaceType.IsGenericType
                let baseInterface = interfaceType.GetGenericTypeDefinition()
                where prop.PropertyType != typeof(string) && baseInterface == typeof(IEnumerable<>) || baseInterface == typeof(IEnumerable)
                select prop;

            foreach (var prop in enumerableTypes)
            {
                var collection = prop.GetValue(first, null);
            }


            return list;
        }

So comparison of all simple types + string works.

Now I would like to iterate through IEnumerable (it's always enumerable of a class, though it would be great to take care of the case when it's not) on both sides and compare values using recursion. Something like this:

foreach (var prop in enumerableTypes)
{
    var typeOfItemsInList= ...;
    var collection1 = (IEnumerable<typeOfItemsInList>) prop.GetValue(first, null);
    var collection2 = (IEnumerable<typeOfItemsInList>) prop.GetValue(second, null);

    for (int i = 0; i < collection1.Count; i++)
    {
        var item1 = collection1[i];
        var item2 = collection2[i];

        Compare<typeOfItemsInList>(item1, item2, list);
    }

}

Unequal count, or order of items in lists are not taken into account here - I would fix it later.





Aucun commentaire:

Enregistrer un commentaire