You can use a Reflection but it may slow your application. An alternative way of creating that comparator is to generate it with Linq Expressions. Try this code:
public static Expression<Func<T, T, bool>> CreateAreEqualExpression<T>(params string[] toExclude)
{
var type = typeof(T);
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => !toExclude.Contains(p.Name))
.ToArray();
var p1 = Expression.Parameter(type, "p1");
var p2 = Expression.Parameter(type, "p2");
Expression body = null;
foreach (var property in props)
{
var pare = Expression.Equal(
Expression.PropertyOrField(p1, property.Name),
Expression.PropertyOrField(p2, property.Name)
);
body = body == null ? pare : Expression.AndAlso(body, pare);
}
if (body == null) // all properties are excluded
body = Expression.Constant(true);
var lambda = Expression.Lambda<Func<T, T, bool>>(body, p1, p2);
return lambda;
}
it will generate an expression that looks like
(Component p1, Component p2) => ((p1.Description == p2.Description) && (p1.Price == p2.Price))
Usage is simple
var comporator = CreateAreEqualExpression<Component>("Id", "DateCreated")
.Compile(); // save compiled comparator somewhere to use it again later
var areEqual = comporator(comp_InApp, comp_InDb);
EDIT: to make it more type safe you can exclude properties using lambdas
public static Expression<Func<T, T, bool>> CreateAreEqualExpression<T>(
params Expression<Func<T, object>>[] toExclude)
{
var exclude = toExclude
.Select(e =>
{
// for properties that is value types (int, DateTime and so on)
var name = ((e.Body as UnaryExpression)?.Operand as MemberExpression)?.Member.Name;
if (name != null)
return name;
// for properties that is reference type
return (e.Body as MemberExpression)?.Member.Name;
})
.Where(n => n != null)
.Distinct()
.ToArray();
var type = typeof(T);
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => !exclude.Contains(p.Name))
.ToArray();
/* rest of code is unchanged */
}
Now when using it we have an IntelliSense support:
var comparator = CreateAreEqualExpression<Component>(
c => c.Id,
c => c.DateCreated)
.Compile();