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

时间:2011-05-12 20:34:20

标签: c# mvvm exception-handling prism 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
    }
}

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

我们:

  1. 首先执行if (MyBar != null)预防可能的NullReferenceException?
  2. 通过验证CanDoFoo()是否返回true来阻止可能的NullReferenceException?
  3. 假设消费视图行为正常并且已经验证它可以调用DoFoo()方法吗?
  4. <小时/> 作为旁注,我问这个的主要原因是因为当我编写单元测试时,我意识到有人可以通过调用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);
        }
    }
    

    第二个场景实际上并没有中断(命令可以正常处理),但是它会在逻辑上分解。那么,我们是第二次通过调用CanDoFoo()来验证业务逻辑还是假设消费视图的行为? (请记住,这只会打破业务逻辑)。

    基本上它可以归结为......我们是否采取了预防措施,以确保消费观点不会因行为不端而陷入困境?

1 个答案:

答案 0 :(得分:5)

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

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

从语义上讲,CanExecute可能与null检查的实现方式不同,因此我只需在Execute方法中执行空检查,而不必检查CanExecute