It all depends on how you weigh, which is equal, which is more important when comparing expressions, etc. For example, if you have a completely different filter, you wonβt be able to find out the difference in queries before executing it.
To provide complete control over your comparison, create a filter class with some properties that you can use to filter, and then build expressions and compare using this class, rather than using visitors. You can prepare a general function for comparing ints, int pairs (for ranges), etc.
I have not tested the code below, but this should be a good start.
public class PersonFilter: IComparable<PersonFilter> { public int? MinAge { get; set; } public int? MaxAge { get; set; } public string NamePrefix { get; set; } public Expression<Predicate<Person>> Filter { return people => people.Where(person => (!MinAge.HasValue || person.Age > MinAge.Value) && (!MaxAge.HasValue || person.Age < MaxAge.Value) && (string.IsNullOrEmpty(NamePrefix) || person.FullName.StartsWith(NamePrefix)) } // -1 if this filter is filtering more than the other public int CompareTo(PersonFilter other) { var balance = 0; // equal if(MinAge.HasValue != other.MinAge.HasValue) { balance += MinAge.HasValue ? -1 : 1; } else if(MinAge.HasValue) { balance += MinAge.Value.CompareTo(other.MinAge.Value) ? } if(string.IsNullOrEmpty(NamePrefix) != string.IsNullOrEmpty(other.NamePrefix)) { balance += string.IsNullOrEmpty(NamePrefix) ? -1 : 1; } else if(!string.IsNullOrEmpty(NamePrefix)) { if(NamePrefix.StartsWith(other.NamePrefix)) { balance -= 1; } else if(other.NamePrefix.StartsWith(NamePrefix)) { balance += 1; } else { // if NamePrefix is the same or completely different let assume both filters are equal } } return balance; } public bool IsSubsetOf(PersonFilter other) { if(MinAge.HasValue != other.MinAge.HasValue) { if(other.MinAge.HasValue) { return false; } } else if(MinAge.HasValue && MinAge.Value < other.MinAge.Value) { return false; } if(string.IsNullOrEmpty(NamePrefix) != string.IsNullOrEmpty(other.NamePrefix)) { if(!string.IsNullOrEmpty(other.NamePrefix)) { return false; } } else if(!string.IsNullOrEmpty(NamePrefix)) { if(!NamePrefix.StartsWith(other.NamePrefix)) { return false; } } return true; } }
too
source share