예제 #1
0
        private static Expression EqualityExpr(Expression oneParam, Expression otherParam, string memberName, Type memberType,
                                               GetMemberAccessor getMemberAccessor)
        {
            if (memberType.IsGenericType && ValidSequenceTypes.Contains(memberType.GetGenericTypeDefinition()))
            {
                return(SequenceEqualsExpr(oneParam, otherParam, memberName, memberType.GenericTypeArguments.Single(), getMemberAccessor));
            }

            if (memberType.IsValueType || ValueTypeEquivalents.Contains(memberType))
            {
                return(EqualOperatorExpr(oneParam, otherParam, memberName, getMemberAccessor));
            }

            if (memberType.GetInterfaces().Any(i =>
                                               i.IsGenericType &&
                                               i.GetGenericTypeDefinition() == typeof(IEquatable <>) &&
                                               i.GenericTypeArguments.Single() == memberType))
            {
                return
                    (Expression.OrElse(
                         EqualOperatorExpr(oneParam, otherParam, memberName, getMemberAccessor),
                         Expression.AndAlso(
                             Expression.Not(
                                 Expression.ExclusiveOr(
                                     Expression.Equal(
                                         getMemberAccessor(oneParam, memberName),
                                         Expression.Constant(null)),
                                     Expression.Equal(
                                         getMemberAccessor(otherParam, memberName),
                                         Expression.Constant(null)))),
                             EqualsExpr(oneParam, otherParam, memberName, memberType, getMemberAccessor))));
            }

            throw new ArgumentException($"cannot handle field {memberName} of type {memberType.FullName}");
        }
예제 #2
0
        private static Func <T, T, bool> ForMembers <T, TMember>(
            IEnumerable <TMember> memberInfos,
            Func <TMember, Type> getMemberType,
            GetMemberAccessor getMemberAccessor)
            where TMember : MemberInfo
        {
            ParameterExpression oneParam   = Expression.Parameter(typeof(T), "one");
            ParameterExpression otherParam = Expression.Parameter(typeof(T), "other");

            if (!memberInfos.Any())
            {
                return(Expression.Lambda <Func <T, T, bool> >(
                           Expression.Constant(true),
                           oneParam,
                           otherParam)
                       .Compile());
            }

            var equalityExpressions = memberInfos.Select(memberInfo =>
                                                         EqualityExpr(oneParam, otherParam, memberInfo.Name, getMemberType(memberInfo), getMemberAccessor));
            var andExpression = equalityExpressions.Aggregate(Expression.AndAlso);

            Expression <Func <T, T, bool> > equalsExpression = Expression.Lambda <Func <T, T, bool> >(
                andExpression,
                new[] { oneParam, otherParam });

            return(equalsExpression.Compile());
        }
예제 #3
0
        private static Expression EqualityExpr(Expression oneParam, Expression otherParam, string memberName, Type memberType,
                                               GetMemberAccessor getMemberAccessor)
        {
            if (memberType.IsValueType || ValueTypeEquivalents.Contains(memberType))
            {
                // one == other
                return(EqualOperatorExpr(oneParam, otherParam, memberName, getMemberAccessor));
            }

            if (memberType.GetInterfaces().Any(i =>
                                               i.IsGenericType &&
                                               i.GetGenericTypeDefinition() == typeof(IEquatable <>) &&
                                               i.GenericTypeArguments.Single() == memberType))
            {
                // one == null ? other == null : one.Equals(other)
                return
                    (Condition(
                         Equal(
                             getMemberAccessor(oneParam, memberName),
                             Constant(null)),
                         Equal(
                             getMemberAccessor(otherParam, memberName),
                             Constant(null)),
                         TypedEqualsExpr(oneParam, otherParam, memberName, memberType, getMemberAccessor)));
            }

            if (new[] { memberType }.Concat(memberType.GetInterfaces()).FirstOrDefault(i =>
                                                                                       i.IsGenericType &&
                                                                                       i.GetGenericTypeDefinition() == typeof(IEnumerable <>)) is Type firstEnumerableType)
            {
                // (one == null && other == null) || (one != null && other != null && Enumerable.SequenceEquals(one, other))
                return
                    (OrElse(
                         AndAlso(
                             Equal(
                                 getMemberAccessor(oneParam, memberName),
                                 Constant(null)),
                             Equal(
                                 getMemberAccessor(otherParam, memberName),
                                 Constant(null))),
                         AndAlso(
                             AndAlso(
                                 NotEqual(
                                     getMemberAccessor(oneParam, memberName),
                                     Constant(null)),
                                 NotEqual(
                                     getMemberAccessor(otherParam, memberName),
                                     Constant(null))),
                             SequenceEqualsExpr(oneParam, otherParam, memberName, firstEnumerableType.GetGenericArguments().Single(), getMemberAccessor))));
            }

            return(ObjectEqualsExpression(oneParam, otherParam, memberName, getMemberAccessor));
        }
예제 #4
0
        private static MethodCallExpression SequenceEqualsExpr(
            Expression oneParam, Expression otherParam, string memberName, Type elementType, GetMemberAccessor getMemberAccessor)
        {
            var enumerableType = typeof(IEnumerable <>).MakeGenericType(elementType);

            return(Expression.Call(
                       null,
                       Methods.SequenceEqual(elementType),
                       Expression.Convert(
                           getMemberAccessor(oneParam, memberName), enumerableType),
                       Expression.Convert(
                           getMemberAccessor(otherParam, memberName), enumerableType)));
        }
예제 #5
0
 private static BinaryExpression EqualOperatorExpr(
     Expression oneParam, Expression otherParam, string fieldName, GetMemberAccessor getMemberAccessor) =>
 Expression.Equal(
     getMemberAccessor(oneParam, fieldName),
     getMemberAccessor(otherParam, fieldName));
예제 #6
0
 private static MethodCallExpression EqualsExpr(
     Expression oneParam, Expression otherParam, string memberName, Type memberType, GetMemberAccessor getMemberAccessor) =>
 Expression.Call(
     getMemberAccessor(oneParam, memberName),
     Methods.EquatableEquals(memberType),
     getMemberAccessor(otherParam, memberName));
예제 #7
0
 private static MethodCallExpression ObjectEqualsExpression
     (Expression oneParam, Expression otherParam, string memberName, GetMemberAccessor getMemberAccessor) =>
 Call(
     Methods.ObjectEquals,
     getMemberAccessor(oneParam, memberName),
     getMemberAccessor(otherParam, memberName));