private static void CheckCompareOption(this DataType type, CompareOption option) { if (!type.IsPrimitive) { throw new NotSupportedException(String.Format("The type '{0}' is not primitive.", type)); } if (type == DataType.String) { if (option.ByteOrder != ByteOrder.Unspecified) { throw new ArgumentException("String can't have ByteOrder option."); } } else if (type == DataType.ByteArray) { if (option.ByteOrder == ByteOrder.Unspecified) { throw new ArgumentException("byte[] must have ByteOrder option."); } } else { if (option.ByteOrder != ByteOrder.Unspecified) { throw new ArgumentException(String.Format("{0} does not support ByteOrder option.", type)); } } }
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(); }
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(); }
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(); }
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(); }
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, Func <Type, MemberInfo, int> membersOrder = null) : this(type, CompareOption.GetDefaultCompareOptions(type, membersOrder), membersOrder) { }
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(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()); }
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()); }
private static IEnumerable <Expression> GetCompareCommands(ParameterExpression data1, ParameterExpression data2, ParameterExpression cmp, LabelTarget exitPoint, DataType slotType, int slotIndex, CompareOption compareOption, bool isLastCompare) { var field1 = Expression.Field(data1, String.Format("Slot{0}", slotIndex)); var field2 = Expression.Field(data2, String.Format("Slot{0}", slotIndex)); var invertCompare = compareOption.SortOrder == SortOrder.Descending; if (slotType == DataType.Boolean) { //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))))); } else if (slotType == DataType.ByteArray) { 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.Return(exitPoint, call)); } } else if (slotType == DataType.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.Return(exitPoint, substract)); } } else if (slotType == DataType.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)); } else if (slotType == DataType.Decimal) { var type = typeof(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.Return(exitPoint, call)); } } else if (slotType == DataType.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.Return(exitPoint, call)); } } else if (slotType == DataType.SByte || slotType == DataType.Byte || slotType == DataType.Int16 || slotType == DataType.Int32 || slotType == DataType.UInt32 || slotType == DataType.UInt16 || slotType == DataType.Int64 || slotType == DataType.UInt64 || slotType == DataType.Single || slotType == DataType.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)), Expression.IfThen(Expression.GreaterThan(field1, field2), Expression.Return(exitPoint, Expression.Constant(greater))))); } else { throw new NotSupportedException(slotType.ToString()); } }
private static IEnumerable <Expression> GetEqualsCommands(ParameterExpression data1, ParameterExpression data2, ParameterExpression equ, LabelTarget exitPoint, DataType slotType, int slotIndex, CompareOption compareOption, bool isLastEqual) { var field1 = Expression.Field(data1, String.Format("Slot{0}", slotIndex)); var field2 = Expression.Field(data2, String.Format("Slot{0}", slotIndex)); if (slotType == DataType.ByteArray) { Debug.Assert(compareOption.ByteOrder != ByteOrder.Unspecified); var order = compareOption.ByteOrder; var equalityComparerType = (order == ByteOrder.BigEndian) ? typeof(BigEndianByteArrayEqualityComparer) : typeof(LittleEndianByteArrayEqualityComparer); var instance = Expression.Field(null, equalityComparerType, "Instance"); var equals = equalityComparerType.GetMethod("Equals", new Type[] { typeof(byte[]), typeof(byte[]) }); var call = Expression.Call(instance, equals, field1, field2); if (!isLastEqual) { //equ = BigEndianByteArrayEqualityComparer.Instance.Equals(field1, field2); //if (equ != false) // return equ; yield return(Expression.Assign(equ, call)); yield return(Expression.IfThen(Expression.NotEqual(equ, Expression.Constant(false)), Expression.Return(exitPoint, equ))); } else { // return BigEndianByteArrayEqualityComparer.Instance.Equals(field1, field2); yield return(Expression.Return(exitPoint, call)); } } else if (slotType == DataType.Char) { if (!isLastEqual) { //if (field1 != field2) // return false; yield return(Expression.IfThen(Expression.NotEqual(field1, field2), Expression.Return(exitPoint, Expression.Constant(false)))); } else { //return field1 == field2; yield return(Expression.Return(exitPoint, Expression.Equal(field1, field2))); } } else if (slotType == DataType.String) { bool optionIgnoreCase = compareOption.IgnoreCase; var type = typeof(String); if (!optionIgnoreCase) { var equals = type.GetMethod("Equals", new Type[] { typeof(string), typeof(string) }); if (!isLastEqual) { //if (!String.Equals(field1, field2)) // return false; yield return(Expression.IfThen(Expression.Not(Expression.Call(equals, field1, field2)), Expression.Return(exitPoint, Expression.Constant(false)))); } else { //return String.Equals(field1, field2); yield return(Expression.Return(exitPoint, Expression.Call(equals, field1, field2))); } } else { var compare = type.GetMethod("Compare", new Type[] { typeof(string), typeof(string), typeof(bool) }); if (!isLastEqual) { //equ = String.Compare(field1, field2, ignoreCase) == 0 //if (!equ) // return false; yield return(Expression.Assign(equ, Expression.Equal(Expression.Call(compare, field1, field2, Expression.Constant(optionIgnoreCase)), Expression.Constant(0)))); yield return(Expression.IfThen(Expression.Not(equ), Expression.Return(exitPoint, Expression.Constant(false)))); } else { //return String.Compare(field1, field2, ignoreCase) == 0; yield return(Expression.Return(exitPoint, Expression.Equal(Expression.Call(compare, field1, field2, Expression.Constant(optionIgnoreCase)), Expression.Constant(0)))); } } } else if (slotType == DataType.Boolean || slotType == DataType.SByte || slotType == DataType.Byte || slotType == DataType.Int16 || slotType == DataType.Int32 || slotType == DataType.UInt32 || slotType == DataType.UInt16 || slotType == DataType.Int64 || slotType == DataType.UInt64 || slotType == DataType.Single || slotType == DataType.Double || slotType == DataType.DateTime || slotType == DataType.Decimal) { if (!isLastEqual) { //if (field1 != field2) // return false; yield return(Expression.IfThen(Expression.NotEqual(field1, field2), Expression.Return(exitPoint, Expression.Constant(false)))); } else { //return field1 == field2 yield return(Expression.Return(exitPoint, Expression.Equal(field1, field2))); } } else { throw new NotSupportedException(slotType.ToString()); } }