В системе, которую я сейчас собираю, я использую шаблон команд для выполнения всех возможных операций. Я выбрал подход CommandMessage и CommandHandler, отделяющий логику от данных.
Пока это работает нормально, но я столкнулся с проблемой - проверка.
Как мне на самом деле проверить, может ли команда выполняться или нет?
Прямо сейчас у меня есть CanExecute(ICommandExecutionContext context)
для каждой команды, что делает ее ответственной за определение того, может ли она выполняться. Затем ICommandExecutionContext
проверяется типом в каждой команде, чтобы узнать, имеет ли он правильный тип контекста, и впоследствии, если информация делает команду исполняемой в этом контексте.
Все обернуто в ICommandService
, который может проверять и выполнять команды, основываясь на их именах, контексте и сообщении. Кроме того, он также публикует события о выполнении команд и выполняет проверки прав доступа.
Проблема связана с пользовательским интерфейсом (приложение ASP.NET MVC 3). Я хотел бы показывать только действительные команды в каждом представлении, но мне не удалось найти решение, которое мне действительно нравится. В настоящее время мой контроллер спрашивает службу команд, может ли команда выполняться, учитывая конкретный контекст, подобный следующему:
var executionContext = new SystemCommandExecutionContext("SignInCommand", CurrentPrincial);
var canExecute = _commandService.CanExecute(executionContext);
/* Handle the result to enable or disable the action link */
Для других типов команд, которые работают с конкретными объектами домена, я использую тот же метод обслуживания команд, но в другом контексте, где я передаю идентификатор объекта домена, например:
[HttpPost, Authorize, ValidateAntiForgeryToken /* etc. */]
public ActionResult Delete(Guid id)
{
/* Note the additional object id in the context */
var executionContext = new EntityCommandExecutionContext("DeletePersonCommand", CurrentPrincipal, id);
var canExecute = _commandService.CanExecute(executionContext);
if(canExecute)
{
var message = new DeletePersonCommandMessage(id);
var isValid = _commandService.IsValid(executionContext, message);
if(isValid)
{
var result = _commandService.Execute(executionContext, message);
/* More logic here... Not very DRY :( */
}
}
}
Полагаю, вышесказанное пока нормально, но не очень СУХОЕ.
Но то, что я хотел бы сделать, это отключить ссылки действий, основанные на результате CanExecute.
Как я могу это сделать?
Я решил «жестко закодировать» все ссылки на команды в каждом представлении, поэтому мне не нужно передавать набор имен команд и т. Д. - этот путь слишком сложен (если у кого-то нет умной идеи;)
Мой текущий стек состоит из NHibernate, Castle Windsor, ASP.NET MVC 3, AutoMapper.