Suppose I have following code:
class Program
{
static IList<Func<object, bool>> _exclusions = new List<Func<object, bool>>();
static void Main(string[] args)
{
SetExclusions<PropertyInfo>(x => typeof(ValueType).IsAssignableFrom(x.PropertyType));
}
public static void SetExclusions<T>(Func<T, bool> lambda)
where T : class
{
Func<object, bool> l = (Func<object, bool>)lambda; // <= InvalidCastException
_exclusions.Add(l);
}
}
Of course it doesn't work because T type parameter in Func is contravariant - I can't pass PropertyInfo as more derived than object.
Is there a way to get around it? From my point of view it would be perfectly correct to do something like this afterwards:
foreach (var e in GetExclusions<PropertyInfo>())
{
var a = members.Where(e);
}
Before suggesting anything, the current design is most probably not appropriated to the problem you need to solve. So I'd really recommend revisiting it whenever there is a chance
Now to your question, one option could be casting the object to the expected type inside the lambda; Something like this:
Func<object, bool> l = o => lambda((T) o);
Then you could keep track in either a Dictionary<Type, Func<object, bool>>
of what type of expressions work for each different Type
. There could be other alternatives if you don't want to keep a dictionary, but they would involve using a class that holds the same information