开发者

Serialising predicates over wcf

开发者 https://www.devze.com 2023-01-28 18:16 出处:网络
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:

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, Expres开发者_如何学JAVAsion<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?


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!


There is absolutely no way you could get your Func<User, bool> across the wire. This expression is stored and will be jitted and will live in the client side world.

Remember, what you are basically doing is to compile an anonymous client-side function by using u => u.Roles.Contains(plebRole). So you would be getting some users that you will filter then later at client side.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号