Как я могу хранить и повторно использовать куски моих лямбда-выражений

У меня есть блок кода, где фрагмент выражения лямбда используется снова и снова. Как сохранить эту логику, чтобы я мог повторно использовать эту часть выражения?

Например: давайте возьмем пример приведенного ниже кода

Session.Query<DimensionGroup>()(dimgroup=>(dimgroup.Users.Where(map => 
((map.User.Key == _users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) &&
map.AccessLevel.ToAccessLevel() == AccessLevel.Write)).Count() > 0));

(map.User.Key == _users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) является частью, которую я хочу повторно использовать.

и аналогичный фрагмент кода...

Session.Query<DimensionGroup>()(dimgroup =>(dimgroup.Users.Where(map => ((map.User.Key
==_users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) &&
map.AccessLevel.ToAccessLevel() ==  AccessLevel.Read)).Count() > 0));

(map.User.Key == _users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) является частью, которую я хочу повторно использовать.

Можно ли каким-то образом повторно использовать только те части выражения?

Ответ 1

Самый простой способ - повторное использование одного выражения lamda, например:

Expression<Func<User, bool>> KeysMatch = 
    map => map.User.Key == _users.PublicUser.Key 
        || map.User.Key == _users.CurrentUser.Key;

Session.Query<DimensionGroup>()(dimgroup=>(
    dimgroup.Users.Where(KeysMatch)
    .Where(map => map.AccessLevel.ToAccessLevel() == AccessLevel.Write))
    .Count() > 0
));

Следующий шаг - фактически изменить сами деревья выражений, вызвав лямбда-выражения. Это сложнее, и если вы не хотите, чтобы с ним справиться и с ним справиться, проще с помощью инструментария. Я предлагаю LinqKit.

Ответ 2

Вы не сказали нам, что лямбда-выражения преобразуются в деревья выражений или для делегатов, но, предполагая первое, я рекомендую использовать PredicateBuilder.

Expression<Map, bool> predicate = map =>  map.User.Key == _users.PublicUser.Key 
                                       || map.User.Key == _users.CurrentUser.Key;

Тогда ваш первый запрос будет выглядеть следующим образом:

var pred1 = predicate.And
            (map => map.AccessLevel.ToAccessLevel() == AccessLevel.Write);

var query1 = Session.Query<DimensionGroup>
    (dimgroup => dimgroup.Users.Where(pred1).Count() > 0);

И ваш второй:

var pred2 = predicate.And
            (map => map.AccessLevel.ToAccessLevel() == AccessLevel.Read);

var query2 = Session.Query<DimensionGroup>
    (dimgroup => dimgroup.Users.Where(pred2).Count() > 0);

Как вы можете видеть, есть возможности для факторизации еще большего числа обычаев; поскольку запросы, по-видимому, отличаются только разными AccessLevel s.

Ответ 3

Func<Map, bool> func = (map => ((((map.User.Key ==_users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) && map.AccessLevel.ToAccessLevel() == AccessLevel.Read)).Count() > 0));

EDIT:

вы можете попробовать что-то вроде этого.

class MyClass{

 Func<Map, bool> func = null;

 MyClass()
 {
    func = (map => ((((map.User.Key ==_users.PublicUser.Key || map.User.Key == _users.CurrentUser.Key) && map.AccessLevel.ToAccessLevel() == AccessLevel.Read)).Count() > 0));
  }
  ...
  ...
}