Serialising predicates over wcf

I have a WCF service that exposes a bunch of methods that return business objects. Under its hood it has a nice repository layer that uses interface methods like this:

IEnumerable<User> GetUsers(Func<User, bool> predicate);

So if I want all users within a given role I can do:

var plebs = GetUsers(u => u.Roles.Contains(plebRole));

Now I want to expose this any-filter-can-be-satisfied thinking over the WCF interface. The WCF api needs to be accessible to non .Net clients so I want to use (relatively) simple types.

I have a Filter object that holds a property name and and value:

[DataContract] public class Filter {
    [DataMember] public string Property { get; set; }
    [DataMember] public string Value { get; set; }
}

So now I can expose a WCF method like this:

IEnumerable<User> GetUsers(IEnumerable<Filter> filters);

Then I can build predicates based on what comes in, in the clients filters. Now it gets 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)
{
  // ReSharper disable PossibleNullReferenceException
  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 },
        ...
      }
    },
    ...
  };
  // ReSharper restore PossibleNullReferenceException
}

Until I started writing the GetKnownPredicates method, the code didn't really stink. Now it does. How do I fix it?

Answers


If you want to be super-fancy you could use the System.Linq.Expressions.Expression class to dynamically build a predicate based on the passed-in filter. You know the type that you're going to search, so all you need to do is to create a property expression using Filter.Property and then a constant expression with Filter.Value. Use them to compose an equal expression and you're near the finish line.

Getting used to composing expressions can be a pain, but the debugger is really helpful and will show you the code for your expression as you compose it, so dive in and try it out!


Need Your Help

Colors in Android

java android function colors return

I am using colors in Android but I don't know the format.

Stack equivelant for tester questions

cucumber

I have some questions relating to cucumber and am looking for the relevant forum to ask questions.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.