Пример #1
0
        public DataEqualityComparer(Type type, CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null)
        {
            Type = type;
            CompareOption.CheckCompareOptions(type, compareOptions, membersOrder);
            CompareOptions = compareOptions;
            MembersOrder   = membersOrder;

            equals      = CreateEqualsMethod().Compile();
            getHashCode = CreateGetHashCodeMethod().Compile();
        }
Пример #2
0
        public Comparer(CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null)
        {
            Type           = typeof(T);
            CompareOptions = compareOptions;
            MembersOrder   = membersOrder;

            CompareOption.CheckCompareOptions(Type, compareOptions, membersOrder);

            compare = CreateCompareMethod().Compile();
        }
Пример #3
0
        public EqualityComparer(CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null)
        {
            CompareOption.CheckCompareOptions(typeof(T), compareOptions, membersOrder);
            Type           = typeof(T);
            CompareOptions = compareOptions;
            MembersOrder   = membersOrder;

            equals      = CreateEquals().Compile();
            getHashCode = CreateGetHashCode().Compile();
        }
Пример #4
0
        public DataComparer(Type type, CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null)
        {
            Type     = type;
            DataType = typeof(Data <>).MakeGenericType(type);

            CompareOption.CheckCompareOptions(type, compareOptions, membersOrder);
            CompareOptions = compareOptions;
            MembersOrder   = membersOrder;

            compare = CreateCompareMethod().Compile();
        }
Пример #5
0
 public Comparer(Func <Type, MemberInfo, int> memberOrder = null)
     : this(CompareOption.GetDefaultCompareOptions(typeof(T), memberOrder), memberOrder)
 {
 }
Пример #6
0
        private static IEnumerable <Expression> GetCompareCommands(Expression x, Expression y, ParameterExpression cmp, LabelTarget exitPoint, Type type, CompareOption compareOption, bool isLastCompare)
        {
            var field1 = x;
            var field2 = y;

            var invertCompare = compareOption.SortOrder == SortOrder.Descending;

            if (type == typeof(bool))
            {
                //if (field1 != field2)
                //{
                //    if (!field1)
                //        return -1;
                //    else
                //        return 1;
                //}

                int less    = !invertCompare ? -1 : 1;
                int greater = !invertCompare ? 1 : -1;

                yield return(Expression.IfThen(Expression.NotEqual(field1, field2),
                                               Expression.IfThenElse(Expression.Not(field1),
                                                                     Expression.Return(exitPoint, Expression.Constant(less)),
                                                                     Expression.Return(exitPoint, Expression.Constant(greater)))));

                if (isLastCompare)
                {
                    yield return(Expression.Label(exitPoint, Expression.Constant(0)));
                }
            }
            else if (type == typeof(Guid))
            {
                if (!isLastCompare)
                {
                    //cmp = field1.CompareTo(field2);
                    //if (cmp != 0)
                    //    return cmp;

                    yield return(Expression.Assign(cmp, Expression.Call(field1, typeof(Guid).GetMethod("CompareTo", new Type[] { typeof(Guid) }), field2)));

                    yield return(Expression.IfThen(Expression.NotEqual(cmp, Expression.Constant(0)),
                                                   Expression.Return(exitPoint, cmp)));
                }
                else
                {
                    //return field1.CompareTo(field2);

                    yield return(Expression.Label(exitPoint, Expression.Call(field1, typeof(Guid).GetMethod("CompareTo", new Type[] { typeof(Guid) }), field2)));
                }
            }
            else if (type == typeof(byte[]))
            {
                Debug.Assert(compareOption.ByteOrder != ByteOrder.Unspecified);

                var order        = compareOption.ByteOrder;
                var comparerType = (order == ByteOrder.BigEndian) ? typeof(BigEndianByteArrayComparer) : typeof(LittleEndianByteArrayComparer);
                var instance     = Expression.Field(null, comparerType, "Instance");
                var compare      = comparerType.GetMethod("Compare", new Type[] { typeof(byte[]), typeof(byte[]) });
                var call         = !invertCompare?Expression.Call(instance, compare, field1, field2) : Expression.Call(instance, compare, field2, field1);

                if (!isLastCompare)
                {
                    //cmp = BigEndianByteArrayComparer.Instance.Compare(field1, field2);
                    //if (cmp != 0)
                    //    return cmp;

                    yield return(Expression.Assign(cmp, call));

                    yield return(Expression.IfThen(Expression.NotEqual(cmp, Expression.Constant(0)),
                                                   Expression.Return(exitPoint, cmp)));
                }
                else
                {
                    //return BigEndianByteArrayComparer.Instance.Compare(field1, field2);

                    yield return(Expression.Label(exitPoint, call));
                }
            }
            else if (type == typeof(char))
            {
                var int1 = Expression.Convert(field1, typeof(int));
                var int2 = Expression.Convert(field2, typeof(int));

                var substract = !invertCompare?Expression.Subtract(int1, int2) : Expression.Subtract(int2, int1);

                if (!isLastCompare)
                {
                    //cmp = (int)field1 - (int)field2;
                    //if (cmp != 0)
                    //    return cmp;

                    yield return(Expression.Assign(cmp, substract));

                    yield return(Expression.IfThen(Expression.NotEqual(cmp, Expression.Constant(0)),
                                                   Expression.Return(exitPoint, cmp)));
                }
                else
                {
                    //return field1 - field2;

                    yield return(Expression.Label(exitPoint, substract));
                }
            }
            else if (type == typeof(DateTime) || type == typeof(TimeSpan))
            {
                //long ticks1 = field1.Ticks;
                //long ticks2 = field2.Ticks;
                //if (ticks1 < ticks2)
                //    return -1;
                //else if (ticks1 > ticks2)
                //    return 1;

                var ticks1 = Expression.Variable(typeof(long));
                var ticks2 = Expression.Variable(typeof(long));

                var assign1 = Expression.Assign(ticks1, Expression.Property(field1, "Ticks"));
                var assign2 = Expression.Assign(ticks2, Expression.Property(field2, "Ticks"));

                int less    = !invertCompare ? -1 : 1;
                int greater = !invertCompare ? 1 : -1;

                var @if = Expression.IfThenElse(Expression.LessThan(ticks1, ticks2),
                                                Expression.Return(exitPoint, Expression.Constant(less)),
                                                Expression.IfThen(Expression.GreaterThan(ticks1, ticks2),
                                                                  Expression.Return(exitPoint, Expression.Constant(greater))));

                yield return(Expression.Block(new ParameterExpression[] { ticks1, ticks2 }, assign1, assign2, @if));

                if (isLastCompare)
                {
                    yield return(Expression.Label(exitPoint, Expression.Constant(0)));
                }
            }
            else if (type == typeof(Decimal))
            {
                var type_    = typeof(System.Collections.Generic.Comparer <>).MakeGenericType(typeof(decimal));
                var @default = Expression.Property(null, type_, "Default");
                var compare  = type_.GetProperty("Default").PropertyType.GetMethod("Compare", new Type[] { typeof(decimal), typeof(decimal) });
                var call     = !invertCompare?Expression.Call(@default, compare, field1, field2) : Expression.Call(@default, compare, field2, field1);

                if (!isLastCompare)
                {
                    //cmp = Comparer<T>.Default.Compare(field1, field2);
                    //if (cmp != 0)
                    //    return cmp;

                    yield return(Expression.Assign(cmp, call));

                    yield return(Expression.IfThen(Expression.NotEqual(cmp, Expression.Constant(0)),
                                                   Expression.Return(exitPoint, cmp)));
                }
                else
                {
                    //return Comparer<T>.Default.Compare(field1, field2);

                    yield return(Expression.Label(exitPoint, call));
                }
            }
            else if (type == typeof(String))
            {
                var  type_            = typeof(string);
                var  compare          = type_.GetMethod("Compare", new Type[] { typeof(string), typeof(string), typeof(bool) });
                bool optionIgnoreCase = compareOption.IgnoreCase;

                var ignoreCase = optionIgnoreCase ? Expression.Constant(optionIgnoreCase) : Expression.Constant(false);
                var call       = !invertCompare?Expression.Call(compare, field1, field2, ignoreCase) : Expression.Call(compare, field2, field1, ignoreCase);

                if (!isLastCompare)
                {
                    //cmp = String.Compare(field1, field2, ignoreCase);
                    //if (cmp != 0)
                    //    return cmp;

                    yield return(Expression.Assign(cmp, call));

                    yield return(Expression.IfThen(Expression.NotEqual(cmp, Expression.Constant(0)),
                                                   Expression.Return(exitPoint, cmp)));
                }
                else
                {
                    //return String.Compare(field1, field2, ignoreCase);

                    yield return(Expression.Label(exitPoint, call));
                }
            }
            else if (type == typeof(SByte) ||
                     type == typeof(Byte) ||
                     type == typeof(Int16) ||
                     type == typeof(Int32) ||
                     type == typeof(UInt32) ||
                     type == typeof(UInt16) ||
                     type == typeof(Int64) ||
                     type == typeof(UInt64) ||
                     type == typeof(Single) ||
                     type == typeof(Double))
            {
                //if (field1 < field2)
                //    return -1;
                //else if (field1 > field2)
                //    return 1;

                int less    = !invertCompare ? -1 : 1;
                int greater = !invertCompare ? 1 : -1;

                yield return(Expression.IfThenElse(Expression.LessThan(field1, field2),
                                                   Expression.Return(exitPoint, Expression.Constant(less, typeof(int))),
                                                   Expression.IfThen(Expression.GreaterThan(field1, field2),
                                                                     Expression.Return(exitPoint, Expression.Constant(greater)))));

                if (isLastCompare)
                {
                    yield return(Expression.Label(exitPoint, Expression.Constant(0)));
                }
            }
            else
            {
                throw new NotSupportedException(type.ToString());
            }
        }
Пример #7
0
 public DataComparer(Type type, Func <Type, MemberInfo, int> membersOrder = null)
     : this(type, CompareOption.GetDefaultCompareOptions(type, membersOrder), membersOrder)
 {
 }
Пример #8
0
        private static Expression GetEqualsCommand(Expression x, Expression y, CompareOption compareOption, LabelTarget exitPoint, bool isLast)
        {
            var type = x.Type;

            if (type == typeof(Boolean) || type == typeof(Char) || type == typeof(SByte) || type == typeof(Byte) ||
                type == typeof(Int16) || type == typeof(UInt16) || type == typeof(Int32) || type == typeof(UInt32) || type == typeof(Int64) || type == typeof(UInt64) ||
                type == typeof(Single) || type == typeof(Double) || type == typeof(DateTime) || type == typeof(TimeSpan) || type == typeof(Decimal))
            {
                if (isLast)
                {
                    return(Expression.Label(exitPoint, Expression.Equal(x, y)));
                }

                return(Expression.IfThen(Expression.NotEqual(x, y),
                                         Expression.Return(exitPoint, Expression.Constant(false))));
            }

            if (type == typeof(string))
            {
                if (compareOption.IgnoreCase)
                {
                    var call = Expression.Call(type.GetMethod("Compare", new Type[] { typeof(string), typeof(string), typeof(bool) }), x, y, Expression.Constant(true));

                    if (isLast)
                    {
                        return(Expression.Label(exitPoint, Expression.Equal(call, Expression.Constant(0, typeof(int)))));
                    }

                    return(Expression.IfThen(Expression.NotEqual(call, Expression.Constant(0, typeof(int))),
                                             Expression.Return(exitPoint, Expression.Constant(false))));
                }
                else
                {
                    var call = Expression.Call(type.GetMethod("Equals", new Type[] { typeof(string), typeof(string) }), x, y);

                    if (isLast)
                    {
                        return(Expression.Label(exitPoint, call));
                    }

                    return(Expression.IfThen(Expression.Not(call), Expression.Return(exitPoint, Expression.Constant(false))));
                }
            }

            if (type == typeof(Guid))
            {
                var equalityComparerType = (compareOption.ByteOrder == ByteOrder.BigEndian) ? typeof(BigEndianByteArrayEqualityComparer) : typeof(LittleEndianByteArrayEqualityComparer);
                var call = Expression.Call(x, typeof(Guid).GetMethod("Equals", new Type[] { typeof(Guid) }), y);

                if (isLast)
                {
                    return(Expression.Label(exitPoint, call));
                }

                return(Expression.IfThen(Expression.Not(call),
                                         Expression.Return(exitPoint, Expression.Constant(false))));
            }

            if (type == typeof(byte[]))
            {
                Debug.Assert(compareOption.ByteOrder != ByteOrder.Unspecified);

                var equalityComparerType = (compareOption.ByteOrder == ByteOrder.BigEndian) ? typeof(BigEndianByteArrayEqualityComparer) : typeof(LittleEndianByteArrayEqualityComparer);
                var call = Expression.Call(Expression.Field(null, equalityComparerType, "Instance"), equalityComparerType.GetMethod("Equals", new Type[] { typeof(byte[]), typeof(byte[]) }), x, y);

                if (isLast)
                {
                    return(Expression.Label(exitPoint, call));
                }

                return(Expression.IfThen(Expression.Not(call),
                                         Expression.Return(exitPoint, Expression.Constant(false))));
            }

            throw new NotSupportedException(type.ToString());
        }