public Comparer(CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null) { Type = typeof(T); CompareOptions = compareOptions; MembersOrder = membersOrder; CompareOption.CheckCompareOptions(Type, compareOptions, membersOrder); LambdaCompare = CreateCompareMethod(); compare = LambdaCompare.Compile(); }
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; LambdaDataComparer = CreateDataCompareMethod(); dataComparer = LambdaDataComparer.Compile(); }
public EqualityComparer(CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null) { Type = typeof(T); CompareOptions = compareOptions; CompareOption.CheckCompareOptions(Type, compareOptions, membersOrder); MembersOrder = membersOrder; LambdaEquals = CreateEquals(); equals = LambdaEquals.Compile(); LambdaGetHashCode = CreateGetHashCode(); getHashCode = LambdaGetHashCode.Compile(); }
public DataEqualityComparer(Type type, CompareOption[] compareOptions, Func <Type, MemberInfo, int> membersOrder = null) { Type = type; CompareOption.CheckCompareOptions(type, compareOptions, membersOrder); CompareOptions = compareOptions; MembersOrder = membersOrder; LambdaEquals = CreateEqualsMethod(); equals = LambdaEquals.Compile(); LambdaGetHashCode = CreateGetHashCodeMethod(); getHashCode = LambdaGetHashCode.Compile(); }
public EqualityComparer(Func <Type, MemberInfo, int> membersOrder = null) : this(CompareOption.GetDefaultCompareOptions(typeof(T), membersOrder), membersOrder) { }
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(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()); }
public DataEqualityComparer(Type type, Func <Type, MemberInfo, int> membersOrder = null) : this(type, CompareOption.GetDefaultCompareOptions(type, membersOrder), membersOrder) { }
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)) { //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()); } }