MVVM:我应该从我的Execute方法中检查我的"CanExecute"方法吗?

m-y*_*m-y 1 c# prism exception-handling mvvm icommand

我理解使用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
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,消费视图可以决定直接调用DoFoo方法(显然破坏了ICommand接口的点)并导致NullReferenceException.这可能有点主观,但我希望采用"标准"方式.

我们要不要:

  1. 通过先做一个防止可能的NullReferenceException if (MyBar != null)
  2. 通过验证CanDoFoo()返回true来防止可能的NullReferenceException ?
  3. 假设消费视图表现正常并且已经验证它可以调用DoFoo()方法?


作为旁注,我问这个的主要原因是因为当我编写单元测试时,我意识到有人可以通过调用Execute()方法而不调用其CanExecute()对应方来破坏我的ViewModel ?显然,在我的单元测试中,我检查是否可以在执行之前执行该方法,但是消费视图可能会决定忽略它.


更新:(场景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);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种情况实际上并没有破坏(命令可以处理正常),但是,它在逻辑上分解.那么,我们是否通过调用CanDoFoo()或假设消费视图的行为来第二次验证业务逻辑?(请记住,这只会破坏业务逻辑).

基本上归结为这个...我们是否采取了预防措施,以确保消费观点不会因行为不当而在脚下射击?

Bri*_*sio 5

在WPF或Silverlight中执行任何命令都会执行此操作,因此您不必担心UI系统中的命令...

但这是一种公共方法.检查null是您可以做的最快的事情之一.它不会受到伤害并且它更加安全,因为你将抛出一个没有guard子句的null异常.

从语义上讲,CanExecute可能与null检查的实现方式不同,所以我只是在Execute方法中进行null检查,不一定要检查CanExecute.