MVVM: я должен проверить мой метод "CanExecute" из моих методов Execute? - PullRequest
1 голос
/ 13 мая 2011

Я понимаю использование CanExecute() и Execute(), но меня интересует следующий сценарий:

public class MyViewModel : NotificationObject
{
    public MyViewModel()
    {
        FooCommand = new DelegateCommand(DoFoo, CanDoFoo);
    }

    public Bar MyBar { get; set; }

    public DelegateCommand FooCommand { get; private set; }

    public Boolean CanDoFoo()
    {
        return (MyBar != null)
    }

    public void DoFoo()
    {
        MyBar.BarFunc(); //Potential for a NullReferenceException
    }
}

По сути, потребительское представление может решить обратиться непосредственно к методу DoFoo (очевидно, нарушая точку интерфейса ICommand) и вызвать исключение NullReferenceException. Это может быть немного субъективно, но я надеюсь на «стандартный» способ сделать это.

Делаем ли мы:

  1. Предотвратить возможное исключение NullReferenceException, выполнив сначала if (MyBar != null)?
  2. Предотвратить возможное исключение NullReferenceException, убедившись, что CanDoFoo() возвращает true?
  3. Предположим, что потребительское представление ведет себя правильно и уже проверило, что оно может вызывать метод DoFoo()?


В качестве примечания, основная причина, по которой я спросил это, заключается в том, что, когда я писал модульные тесты, я понял, что кто-то может сломать мою ViewModel, вызывая Execute() методы, не вызывая их CanExecute() аналогов? Очевидно, что в своих модульных тестах я проверяю, могу ли я выполнить метод до выполнения этого, но потребляющие представления могут решить игнорировать это.


Обновление: (Сценарий 2)

В качестве дополнения к этому вопросу я также хочу добавить в сценарий, где метод DoFoo() не нарушает с точки зрения исключений, но может логически сломаться?

public class MyViewModel : NotificationObject
{
    public MyViewModel()
    {
        FooCommand = new DelegateCommand(DoFoo, CanDoFoo);
    }

    public Int32 Age { get; set; }

    public DelegateCommand FooCommand { get; private set; }

    public Boolean CanDoFoo()
    {
        return (Age >= 21)
    }

    public void DoFoo()
    {
        ProvideAlcohal(Age);
    }
}

Этот второй сценарий на самом деле не прерывается (команда может нормально работать), однако он логически разбивается. Итак, мы проверяем бизнес-логику во второй раз, вызывая CanDoFoo() или предполагаем, что потребительское представление ведет себя? (Помните, это только нарушает бизнес-логику ).

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

1 Ответ

5 голосов
/ 13 мая 2011

Любая реализация вызова команд в WPF или Silverlight сделает это, поэтому вам не нужно беспокоиться об этом из системы пользовательского интерфейса ...

Но это публичный метод.Проверка на ноль - одна из самых быстрых вещей, которые вы можете сделать.Это не повредит, и это намного более безопасно, так как вы выбросите пустое исключение без выражения охраны.

Семантически, CanExecute может быть реализовано не так, как проверка нуля, поэтому я бы просто сделал нольотметьте в методе Execute, не обязательно проверяйте CanExecute.

...