I have a WCF service that provides a bunch of methods that return business objects. Under the hood, he has a good repository level that uses interface methods such as this:
IEnumerable<User> GetUsers(Func<User, bool> predicate);
So, if I want all users in this role to be able to do:
var plebs = GetUsers(u => u.Roles.Contains(plebRole));
Now I want to expose this opinion, which can be executed by any filter through the WCF interface. WCF api should be available for non.Net clients, so I want to use (relatively) simple types.
I have a Filter object that contains the property name and value:
[DataContract] public class Filter {
[DataMember] public string Property { get; set; }
[DataMember] public string Value { get; set; }
}
So, now I can set the WCF method as follows:
IEnumerable<User> GetUsers(IEnumerable<Filter> filters);
Then I can build predicates based on what goes into client filters. Now this is getting messy:
private static Expression<Func<T, bool>> GetPredicate<T>(Filter filter)
{
var knownPredicates = GetKnownPredicates<T>(filter.Value);
var t = typeof(T);
return knownPredicates.ContainsKey(t) && knownPredicates[t].ContainsKey(filter.Property)
? knownPredicates[t][filter.Property]
: True<T>();
}
private static Dictionary<Type, Dictionary<string, Expression<Func<T, bool>>>> GetKnownPredicates<T>(string value)
{
return new Dictionary<Type, Dictionary<string, Expression<Func<T, bool>>>>
{
{
typeof (User), new Dictionary<string, Expression<Func<T, bool>>>
{
{ "Forename", x => (x as User).Forename == value },
{ "IsAdult", x => (x as User).IsAdult.ToString() == value },
...
}
},
{
typeof (Group), new Dictionary<string, Expression<Func<T, bool>>>
{
{ "Name", x => (x as Group).Name == value },
...
}
},
...
};
}
GetKnownPredicates, . . ?