I have a situation in which i would like to filter objects based on collections of predicates imposed on their particular types:
Could this be done via precompiled ExpressionTrees
?
class A
{
public int Value {get;set;}
}
class B
{
public string Name {get;set;}
public bool IsMajor{get;set;}
}
Dictionary<Type,IEnumerable<Predicate<[object casted to type]>> typePredicateMap=new Dictionary<Type,Predicate<[object casted to type]>>{
{typeof(A),new List<Predicate<[object casted to A]> { x=>x.Value >100,x=>x.Value<200 }},
{typeof(B),new List<Predicate<[object casted to B]> { x=>x.Name!="johhnny",x=>x.IsMajor==true }}
}
I said above object casted to Type
since i want my predicate to be based on that particular type..
public static bool MeetsCriteria(object data)
{
Type type=typeof(data);
IEnumerable<Predicate<object>predicates=typePredicateMap[type];
bool isValid=true;
foreach(var predicate in predicates)
{
isValid&=predicate(data); //
}
return isValid;
}
The main issue is that since we want to dynamically choose the predicates to call, they need to be of type Predicate<object>
, since the type we are invoking them on is object
. Due to the fact that Predicate<T>
is contravariant (defined as Predicate<in T>
), that means that we can specify a less-derived type for T where a more derived type is expected.
In practice that means that if you had a class A
and class B : A
, you could use a Predicate<A>
as a Predicate<B>
or a Predicate<object>
as Predicate<A>
, but you can't do Predicate<A>
where Predicate<object>
is expected. This means that your predicates will have to be of type Predicate<object>
and cast the object parameter to the right type manually.
I guess that was a long-winded way of saying you just have to use Predicate<object>
everywhere, or find some way to constrain your input objects. Does your MeetsCriteria
method really need to handle every object which might ever exist?
I don't believe what your are asking for is possible to solve with expression trees since the problem with types will still be present, but hey, maybe someone will prove me wrong.