У меня есть служба WCF, которая предоставляет набор методов, которые возвращают бизнес-объекты. Под капотом у него есть хороший слой репозитория, который использует такие методы интерфейса:
IEnumerable<User> GetUsers(Func<User, bool> predicate);
Итак, если я хочу, чтобы все пользователи в рамках данной роли, я мог сделать:
var plebs = GetUsers(u => u.Roles.Contains(plebRole));
Теперь я хочу показать, что любой фильтр может быть удовлетворен размышлениями об интерфейсе WCF. API WCF должен быть доступен не для клиентов .Net, поэтому я хочу использовать (относительно) простые типы.
У меня есть объект Filter, который содержит имя и значение свойства:
[DataContract] public class Filter {
[DataMember] public string Property { get; set; }
[DataMember] public string Value { get; set; }
}
Так что теперь я могу представить метод WCF следующим образом:
IEnumerable<User> GetUsers(IEnumerable<Filter> filters);
Затем я могу строить предикаты на основе того, что входит в фильтры клиентов. Теперь это становится грязным:
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
}
Пока я не начал писать метод GetKnownPredicates, код действительно не вонял. Теперь это так. Как мне это исправить?