Как я могу преобразовать предикат <T>в выражениеиспользовать с Moq? - PullRequest
6 голосов
/ 21 октября 2010

Пожалуйста, помогите этому новичку Linq!

Я создаю список в тестируемом классе и хочу использовать Moq для проверки результатов.

Я могу легко собратьПредикат, который проверяет результаты списка.Как мне тогда превратить этот Предикат в Выражение?

var myList = new List<int> {1, 2, 3};

Predicate<List<int>> myPredicate = (list) => 
                  {
                      return list.Count == 3; // amongst other stuff
                  };

// ... do my stuff

myMock.Verify(m => m.DidStuffWith(It.Is<List<int>>( ??? )));

???должен быть Expression<Predicate<List<int>>>, если вы можете собрать столько дженериков.Я нашел ответы, которые делают это наоборот и собирают выражение в предикат.Они не помогают мне лучше понять Linq.

РЕДАКТИРОВАТЬ: у меня это работает с методами;с выражениями;Я просто хотел бы знать, есть ли способ сделать это с лямбдой с телом - и если нет, то почему бы и нет?

Ответы [ 2 ]

5 голосов
/ 21 октября 2010

Изменение:

Predicate<List<int>> myPredicate = (list) => list.Count == 3;

Кому:

Expression<Predicate<List<int>>> myPredicate = (list) => list.Count == 3;

Компилятор делает магию за вас. При некоторых предостережениях 1 любая лямбда, имеющая дело только с выражениями (без блоков), может быть преобразована в дерево выражений, заключив тип делегата (в данном случае Predicate<List<int>>) в Expression<>. Как вы заметили, вы можете затем снова инвертировать его, позвонив myPredicate.Compile().

1 Например, асинхронные лямбда-выражения (т.е. async () => await Task.Delay(1);) нельзя преобразовать в дерево выражений.

Обновление: Вы просто не можете использовать компилятор для получения нужного дерева выражений, если оно включает операторов . Вам придется создать дерево выражений самостоятельно (намного больше работы), используя статические методы в Expression. (Expression.Block, Expression.IfThen и т. Д.)

1 голос
/ 22 октября 2010

Ответ Кирка Уолла непосредственно касается вашего вопроса, но примите во внимание тот факт, что вы можете использовать метод Callback для Setup метода void для обработки параметров, переданных при вызове.Это имеет больше смысла для меня, так как вы уже должны создать метод для проверки списка в любом случае;он также дает вам локальную копию списка.

//what is this list used for?
var myList = new List<int> {1, 2, 3};

List<int> listWithWhichStuffWasDone = null;
//other setup

myMock.Setup(m => m.DoStuffWith(It.IsAny<List<int>>()).
    Callback<List<int>>(l => listWithWhichStufFWasDone = l);

objectUnderTest.MethodUnderTest();

myMock.Verify(m => m.DoStuffWith(It.IsAny<List<int>>()));
Validate(listWithWhichStuffWasDone);
...