Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ICommand - Should I call CanExecute in Execute?

Given that System.Windows.Input.ICommand as 2 primary methods:

interface ICommand {
  void Execute(object parameters);
  bool CanExecute(object parameters);
  ...
}

I expect CanExecute(...) to be called in the Command-supported frameworks before Execute(...) is called.

Internally to my Command Implementation, however, is there any reason to add the CanExecute(...) call inside my Execute(...) implementation?

e.g.:

public void Execute(object parameters){
  if(!CanExecute(parameters)) throw new ApplicationException("...");
  /** Execute implementation **/
}

This becomes relevant in my testing, as I may mock out some interfaces to support CanExecute, and have to do the same mocks when testing Execute.

Any design thoughts on this?

like image 804
Sheldon Warkentin Avatar asked Aug 08 '11 15:08

Sheldon Warkentin


People also ask

Which method of ICommand will let you know if command can be executed or not?

CanExecute will determine whether the command can be executed or not. If it returns false the button will be disabled on the interface.

What are the methods of ICommand?

ICommand is an interface between the Presentation & the BusinessLogic layer. Whenever any button is pressed on the screen, XAML has its code-behind ButtonClick event. But in MVVM architecture, there is no room for code-behind to keep the application loosely coupled, so ICommand was introduced.

Can execute changed WPF?

No you can not use it to change the can execute state. It is an event and objects which participate in the ICommand pattern can choose to listen to this event e.g. a button may use this event to know when to re-query the commands state (by calling the can execute method) to set its enabled state.


3 Answers

Programmers are notoriously lazy and they will call Execute without calling CanExecute first.

The ICommand interface is more often used with the WPF binding framework however it is an extremely robust and useful pattern that can be used elsewhere.

I call CanExecute immediately from the Execute method to validate the state of the object. It helps reduce duplicate logic and enforces the use of the CanExecute method (why go through all the effort of whether they can call a method and not bother enforcing it?). I don't see a problem with calling CanExecute lots of times because it should be a quick operation anyway.

I do however always document the results of calling an Execute method if the CanExecute method returns false, so that the consumer knows the consequences.

like image 59
Siy Williams Avatar answered Oct 09 '22 10:10

Siy Williams


I would not be as optimistic as others about adding a call to CanExecute into Execute implementation. What if your CanExecute execution takes a very long time to complete? This would mean that in real-life your user will wait twice that long - once when CanExecute is called by environment, and then when it is called by you.

You could possibly add some flags to check whether CanExecute has already been called, but be careful to keep them always up to command state not to miss or perform unwanted CanExecute call when the state has changed.

like image 20
Michael Sagalovich Avatar answered Oct 09 '22 09:10

Michael Sagalovich


I would go one way or the other, but not both.

If you expect the user to call CanExecute, then don't call it in Execute. You've already set that expectation in your interface and now you have a contract with all the developers that implies this sort of interaction with ICommand.

However, if you're worried about developers not utilizing it properly (as you could rightfully be), then I would suggest removing it from the interface completely, and making it an implementation concern.

Example:

interface Command {
    void Execute(object parameters);    
}

class CommandImpl: ICommand {
    public void Execute(object parameters){
        if(!CanExecute(parameters)) throw new ApplicationException("...");
        /** Execute implementation **/
    }
    private bool CanExecute(object parameters){
        //do your check here
    }
}

This way, you're contract (interface) is clear and concise, and you won't be confused about whether or not CanExecute is getting called twice.

However, if you're actually stuck with the interface because you don't control it, another solution could be to store the results and check it like this:

interface Command {
    void Execute(object parameters);    
    bool CanExecute(object parameters);
}

class CommandImpl: ICommand {

    private IDictionary<object, bool> ParametersChecked {get; set;}

    public void Execute(object parameters){
        if(!CanExecute(parameters)) throw new ApplicationException("...");
        /** Execute implementation **/
    }

    public bool CanExecute(object parameters){
        if (ParametersChecked.ContainsKey(parameters))
            return ParametersChecked[parameters];
        var result = ... // your check here

        //method to check the store and add or replace if necessary
        AddResultsToParametersChecked(parameters, result); 
    }
}
like image 37
Joseph Avatar answered Oct 09 '22 09:10

Joseph