public static Expression <Func <T, T, bool> > comparisonGenerator <T>() { var ourType = typeof(T); var members = ourType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.CustomAttributes.Any(ca => ca.AttributeType == typeof(EquatableItemAttribute))); var exprList = new List <BinaryExpression>(members.Count()); var param1 = Expression.Parameter(ourType); var param2 = Expression.Parameter(ourType); foreach (MemberInfo element in members) { BinaryExpression eq1 = null; var accessor1 = Expression.PropertyOrField(param1, element.Name); var accessor2 = Expression.PropertyOrField(param2, element.Name); if (isString(element)) { var compVal = Expression.Constant(element.GetCustomAttribute <EquatableItemAttribute>().StringComparison); var stringCompare = typeof(string).GetMethod("Equals", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string), typeof(string), typeof(StringComparison) }, null); eq1 = Expression.Equal(Expression.Call(stringCompare, accessor1, accessor2, compVal), Expression.Constant(true)); } else if (isEasyEquatable(element)) { //Call our EasyEquatable method. eq1 = Expression.Equal(Expression.Call(typeof(IEasyEquatableExtensions), "CompareEasyEquatable", new[] { MemberInfoHelpers.getType(element) }, accessor1, accessor2), Expression.Constant(true)); } else if (isEquatable(element) && !isPrimitive(element)) { //If here, we have Equatable //(And aren't dealing with something so simple we should just fall-through.) eq1 = Expression.Equal(Expression.Call(typeof(IEasyEquatableExtensions), "CompareEquatable", new[] { MemberInfoHelpers.getType(element) }, accessor1, accessor2), Expression.Constant(true)); } //Default case: We just do Expression.Equals. if (eq1 == null) { eq1 = Expression.Equal(accessor1, accessor2); } exprList.Add(eq1); } var currentExpr = exprList[0]; if (exprList.Count > 1) { for (int i = 1; i < exprList.Count; i++) { currentExpr = Expression.AndAlso(currentExpr, exprList[i]); } } var compFunc = Expression.Lambda <Func <T, T, bool> >(currentExpr, param1, param2); return(compFunc); }
private static bool isPrimitive(MemberInfo element) { return(MemberInfoHelpers.getType(element).IsPrimitive); }