Vous pouvez utiliser une réflexion, mais cela risque de ralentir votre application. Une autre façon de créer ce comparateur est de le générer avec des expressions Linq. Essayez ce 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;
}
il génère une expression qui ressemble à
(Component p1, Component p2) => ((p1.Description == p2.Description) && (p1.Price == p2.Price))
L'utilisation est 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 Pour plus de sécurité, vous pouvez exclure des propriétés à l'aide de 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 */
}
Désormais, lors de son utilisation, nous disposons d'un support IntelliSense :
var comparator = CreateAreEqualExpression<Component>(
c => c.Id,
c => c.DateCreated)
.Compile();