Я пытаюсь сделать переход от PHP к ASP.NET, и при этом я пытаюсь узнать, как работает MVC, однако я застрял с ControllerActionInvoker.InvokeActionMethodWithFilters, поскольку я не понимаю, что происходит.
Фрагмент, с которым я борюсь, следующий:
protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
(next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
return thunk();
}
Полный исходный код можно найти по следующему URL-адресу: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/ControllerActionInvoker.cs#L371
В частности, я не уверен, что делает следующее:
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
Поскольку я никогда не видел строку, содержащую следующее: continue =() =>
Я также не могу найти ответ на Google, потому что он не признает =() => в качестве условия поиска.
Я так же путаюсь со следующим фрагментом кода, который имеет похожий синтаксис:
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
(next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
Исходя из фона PHP, я раньше этого синтаксиса не видел, и ресурсы, которые я читал в Интернете, на самом деле тоже не очень понятны для меня.
На основе следующего SO-вопроса: делегирование ключевого слова против лямбда-нотации
Если бы мне пришлось переписать следующее...
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
Было бы так...
Func<ActionExecutedContext> continuation = delegate(new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */))
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
И то же самое для второго фрагмента...
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
(next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
Который, если я не ошибаюсь, был бы...
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation, delegate(next, filter) {InvokeActionMethodFilter(filter, preContext, next)});
Или я все еще не понимаю?
Это лямбда-выражения, и в этом конкретном случае это не более чем анонимные функции.
Который, если я не ошибаюсь, был бы...
Неправильно. Делегат должен работать с двумя параметрами next
и filter
, который возвращает делегат другой функции, InvokeActionMethodFilter
метод InvokeActionMethodFilter
:
Func<ActionExecutedContext> thunk =
filters.Reverse()
.Aggregate(continuation,
delegate(Func<ActionExecutedContext> next, IActionFilter filter)
{
return delegate
{
return InvokeActionMethodFilter(filter, preContext, next);
};
});
Этот код вызывает вызов IActionFilters, пока некоторые из них не приведут к результату. И в конце цепи - ваш метод действий. next
переменная - либо функция выполнения фильтра () => InvokeActionMethodFilter(filter, preContext, next)
, либо continuation
в конце цепочки. Для InvokeActionMethodFilter
дополнительной информации см. Реализацию InvokeActionMethodFilter
.
= () =>
, это назначение анонимного делегата.