Posted by: Zeeshan Amjad | August 4, 2011

Implement ICommand interface


We already saw the implementation of ICommand interface here, here and here. That was very naïve implementation. The biggest problem with this implementation is that we can’t pass the predicate (a method whose return type is Boolean) to decide that command can be executed or not. The other problem is that Action is defined as a public property, means anyone can change it after creating an object of that class.

Now in first step we are going to handle these two problems. We convert property into private field and introduce one more field of Func<bool> type to store predicate.

Now implementation of CanExecute method is changed little bit. It checks if predicate is assigned. If predicate is assigned then use its return type to decide command can execute or not, otherwise return true. Here is updated version of our ICommand interface implementation.

Code Snippet
public class MyCommand : ICommand
{
    private Action _Function;
    private Func<bool> _Predicate;

    public MyCommand(Action function)
    {
        _Function = function;
    }

    public MyCommand(Action function, Func<bool> predicate)
    {
        _Function = function;
        _Predicate = predicate;
    }

    public bool CanExecute(object parameter)
    {
        if (_Predicate != null)
        {
            return _Predicate();
        }

        return true;
    }

    public void Execute(object parameter)
    {
        if (_Function != null)
        {
            _Function();
        }
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

 

Now we can assigned the predicate at the time of creating an object of this class. If we don’t have any predicate, then we can even use lambda expression or leave it. Here is one example.

Code Snippet
CalculateAmortizationCommand = new MyCommand(CalculatePayment, () => true);
ExitCommand = new MyCommand(Close);

 

We assigned the predicate with lambda expression in first statement and leave it in second statement.

Now we can go one step forward and see how can we pass the parameter to the method. For this we convert our MyCommand class into generic type and passed one generic parameter. We use this generic parameter to pass parameter to our command.

Our class is something like this now.

Code Snippet
public class MyCommand<T> : ICommand
{
    private Action<T> _Function;
    private Func<bool> _Predicate;

    public MyCommand(Action<T> function)
    {
        _Function = function;
    }

    public MyCommand(Action<T> function, Func<bool> predicate)
    {
        _Function = function;
        _Predicate = predicate;
    }

    // other stuff
}

 

Now we are going to take an advantage of this parameter and convert our ExecuteMethod something like this.

Code Snippet
public void Execute(T parameter)
{
    if (_Function != null)
    {
        _Function(parameter);
    }
}

 

Now we have a problem. We haven’t implemented all of the method of ICommand interface because that method must take object type as a parameter. Therefore we have to overload this method to make sure we implement that method and call our generic type parameter from there. Here is Execute method that takes object as a parameter.

Code Snippet
public void Execute(object parameter)
{
    Execute((T)parameter);
}

 

We can do the same thing with predicate method, i.e. pass parameter to predicate method. Now we have two types passed as a parameter to our class, it looks something like this.

Code Snippet
public class MyCommand<T1, T2> : ICommand
{
    private Action<T1> _Function;
    private Func<T2, bool> _Predicate;

    public MyCommand(Action<T1> function)
    {
        _Function = function;
    }

    public MyCommand(Action<T1> function, Func<T2, bool> predicate)
    {
        _Function = function;
        _Predicate = predicate;
    }

    // other stuff
}

 

Now we have to create the same thing for CanExecute method i.e. overload it. Here is complete coding of our MyCommad class.

Code Snippet
public class MyCommand<T1, T2> : ICommand
{
    private Action<T1> _Function;
    private Func<T2, bool> _Predicate;

    public MyCommand(Action<T1> function)
    {
        _Function = function;
    }

    public MyCommand(Action<T1> function, Func<T2, bool> predicate)
    {
        _Function = function;
        _Predicate = predicate;
    }

    public void Execute(T1 parameter)
    {
        if (_Function != null)
        {
            _Function(parameter);
        }
    }

    public bool CanExecute(T2 parameter)
    {
        if (_Predicate != null)
        {
            return _Predicate(parameter);
        }

        return true;
    }

    #region Implement ICommand interface
    
    public bool CanExecute(object parameter)
    {
        return CanExecute((T2)parameter);
    }

    public void Execute(object parameter)
    {
        Execute((T1)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    #endregion
}

 

Now we have to change the usage of this class too little bit. Here is an update code of using this class.

Code Snippet
CalculateAmortizationCommand = new MyCommand<object, object>(CalculatePayment, (object parameter) => true);
ExitCommand = new MyCommand<object, object>(Close);

 

Now our method “CalculatePayment” and “Close” take one parameter and the type of the parameter is generic.

We can even make one more field of type Action for commands which don’t have any parameter. In this case we don’t have to change the signature of “CalculatePayment” and “Close” methods.

Although we can do the same with predicate (i.e. create one with parameter and one without it), but I leave it with only one predicate that accept one parameter. Here is a final version of our class.

Code Snippet
public class MyCommand<T1, T2> : ICommand
{
    private Action _FunctionWithParam;
    private Action<T1> _Function;
    private Func<T2, bool> _Predicate;

    public MyCommand(Action functionWithoutParam)
    {
        _FunctionWithParam = functionWithoutParam;
    }

    public MyCommand(Action<T1> function)
    {
        _Function = function;
    }

    public MyCommand(Action functionWithoutParam, Func<T2, bool> predicate)
    {
        _FunctionWithParam = functionWithoutParam;
        _Predicate = predicate;
    }

    public MyCommand(Action<T1> function, Func<T2, bool> predicate)
    {
        _Function = function;
        _Predicate = predicate;
    }

    public void Execute(T1 parameter)
    {
        if (_Function != null)
        {
            _Function(parameter);
        }
    }

    public bool CanExecute(T2 parameter)
    {
        if (_Predicate != null)
        {
            return _Predicate(parameter);
        }

        return true;
    }

    #region Implement ICommand interface
    
    public bool CanExecute(object parameter)
    {
        return CanExecute((T2)parameter);
    }

    public void Execute(object parameter)
    {
        if (_FunctionWithParam != null)
        {
            _FunctionWithParam();
        }
        else
        {
            Execute((T1)parameter);
        }
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    #endregion
}

Advertisements

Responses

  1. […] It is better to have some reusable classes to implement some functionality. We have one implementation of ICommand interface here. […]

  2. […] Let’s first do some infrastructure work. Here is my simple implementation of ICommand interface. This is not a general purpose implementation of ICommand interface, because we simply ignore the predicate and command parameter, but for this small project this is enough. You can see the more general implementation here. […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: