Accepted answer

Try to avoid reflection because it can slow down your application. As an alternative you can create a dictionary and put all comparators into it:

var configDictionary = new Dictionary<string, List<Func<object, object, bool>>>
        new List<Func<object, object, bool>>
            (b1, b2) => ((Book)b1).Title == ((Book)b2).Title,
            (b1, b2) => ((Book)b1).CoverImage == ((Book)b2).CoverImage,
            (b1, b2) => ((Book)b1).NumberOfPages == ((Book)b2).NumberOfPages,
            (b1, b2) => ((Book)b1).Id != ((Book)b2).Id,
    // same for Authors

Now you can use it in Where method:

var typeName = obj.GetType().Name; // here we using Reflection but once per collection, not per each item
var first = someList.Where(x => configDictionary[typeName].All(f => f(x, obj))).FirstOrDefault();

Also, because FirstOrDefault also has overload that accept predicate last line can be rewritten to:

var first = someList.FirstOrDefault(x => configDictionary[typeName].All(f => f(x, obj)));


A better solution will be creating custom attribute which will tag property. Then in class override default method Equals which will get all properties with this attribute and return equality.

Related Articles