-
-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using default comparer builder option throws StackOverflowException. #25
Comments
The |
This throws an exception
|
Yes, the Again, what behavior were you expecting? |
I expected it to compare one property at a time and return true. |
I may be wrong but I don't think using |
@amir734jj: Nito.Comparers does not reflect over all properties of types. That's rarely the desired behavior. The |
I understand. I am passionate about this subject because I spend too much time daily writing and maintaining public class Component
{
public double AccumulatedWeight { get; set; }
public double Weight { get; set; }
public Nested NestedRef { get; set; }
}
public class Nested
{
public double NestedProp { get; set; }
}
class Program
{
static void Main(string[] args)
{
var c1 = new Component
{
Weight = 0.7,
AccumulatedWeight = 0.2,
NestedRef = new Nested
{
NestedProp = 223
}
};
var c2 = new Component
{
Weight = 0.7,
AccumulatedWeight = 0.2,
NestedRef = new Nested
{
NestedProp = 223
}
};
var result = BuildEquals<Component>()(c1, c2);
Console.WriteLine(result);
}
public static Func<T, T, bool> BuildEquals<T>()
{
return ((Expression<Func<T, T, bool>>) BuildEquals(typeof(T))).Compile();
}
public static Expression BuildEquals(Type type)
{
bool IsComplexType(Type nestedType)
{
return !nestedType.Namespace.StartsWith("System.Collections") && nestedType.IsClass;
}
var arg1 = Expression.Parameter(type);
var arg2 = Expression.Parameter(type);
var body = type
.GetProperties()
.Select(x =>
{
if (IsComplexType(x.PropertyType))
{
return (Expression) Expression.Invoke(BuildEquals(x.PropertyType),
Expression.Property(arg1, x.Name),
Expression.Property(arg2, x.Name));
}
else
{
return Expression.Equal(Expression.Property(arg1, x.Name), Expression.Property(arg2, x.Name));
}
})
.Aggregate((x, y) => Expression.And(x, y));
return Expression.Lambda(body, arg1, arg2);
} |
You can use a similar approach to public static IFullEqualityComparer<T> BuildAllMembersEqualityComparer<T>()
{
var result = EqualityComparerBuilder.For<T>().Null();
var type = typeof(T);
var parameter = Expression.Parameter(type);
foreach (var prop in type.GetProperties())
{
var expression = Expression.Property(parameter, prop.Name);
dynamic selector = Expression.Lambda(expression, parameter).Compile();
dynamic childComparer = null;
if (IsComplexType(prop.PropertyType))
childComparer = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(prop.PropertyType).Invoke(null, null);
result = EqualityComparerExtensions.ThenEquateBy(result, selector, childComparer);
}
return result;
bool IsComplexType(Type nestedType) => !nestedType.Namespace.StartsWith("System.Collections") && nestedType.IsClass;
} This code takes a similar approach as run-time comparers: starting with Using Nito.Comparers in this way, the same lambda expressions are used to implement both |
Using
Default
throws StackOverflowException exception but usingOrderBy(x => x.Weight)
works fine.The text was updated successfully, but these errors were encountered: