Command Manager

Today I want to tell you about the pattern Command and Command Manager. All this went smoothly. In the last article, this is so and suggests itself, but I was too lazy to twist it back, I decided to tell apart. Although at first I had doubts as to whether to tell all. Because I go to distribute the 5 ways to implement (as the complexity and development of the idea, but then one still rejected), and this functionality is even more developed and built in WPF. In the end, I think it will be useful to beginners, to be better understood how to use it in the future, in WPF, and in general.

Let’s start with the official part, that’s what Wikipedia tells us about the purpose of this template:

Command – a design pattern used in object-oriented programming, which is for an action. The command object contains the action itself and its parameters. Provides processing commands in the form of an object that allows you to save her, to pass as a parameter of the method, and return it as a result, like any other object.

From the definition we can say that with the help of commands to make the application less connected with each other. This can be useful for writing plug-ins when there are different implementations of a single action, when to run the program, with arbitrary initial actions identified in the command line, for example.

Most, if not all, interaction with the user in Visual Studio is built on the commands. As proof, you can open Tools > Options > Environment > Keyboard and you see commands that can be binded to hotkeys. The same action can make the menu. Some acts are of plug-ins to the studio. Something makes the studio itself, as a result of remembering your actions (opening the latest working files for the project is opened) – all this is the result of a template. Otherwise would have been just a terrible linkage\references and Overobject – Oriented Programming.

In the disadvantages to this method can be written using non-obviousness in the final code and code complexity investigation without executing it.
General view of the pattern shown in the diagram below.

Do not worry, in real life it would be simplier.

Beginning

Let’s start with the simplest and elementary way.
Command will be without any parameters, just content for some action.

public class Command {
    private readonly Action action;

    public Command(Action action) {
        this.action = action;
     }

    public void Execute() {
        if (action == null) return;
        action();
    }
}

In this example, the action specified by the constructor, but you can do the same through the property, no problem in that I do not see.

In view of the fact that I prefer the interface polymorphism, for the latitude of the interface I’ve highlighted in this class, only to put the first command to complete.

public interface ICommand {
    void Execute();
}

On this backbone will be built and all the rest, the evolution in action .In order to have access to pre-established command, you need a centralized repository. This is so that you can reach of anywhere up to him and call the appropriate command in the least action. This store is said to be Command Manager.

public static class CommandManager {
    private static readonly Dictionary<string, ICommand> commands = new Dictionary<string, ICommand>();

    public static void RegisterCommand(string commandName, ICommand command) {
        commands[commandName] = command;
    }

    public static void Execute(string commandName) {
        commands[commandName].Execute();
    }
}

In its simplest form, the class is also simple. In this case, the class is made static, as in the example does not present the service locator. Heh, even though by itself it is also the manager and will have the same structure, only to give services on interfaces.

So, the command manager is used to store a dictionary key is the name of the command. Commands themselves are written on the interface. To make life more comfortable, I suggest to define a static class with the names of commands. Or you can use this enumerator.

var command = new Command(DoJob);
CommandManager.RegisterCommand("Job", command);

Using the same will be in this way

CommandManager.Execute("Job");

The first improvement

The second method extends the possibilities for recognition and usage. You will need only a little to improve Command Manager. , a unique key will be not only a command name and its associated type. This will create the same command for different data types. This will be achieved by using the type sequence.

public static class CommandManager {
    private static readonly Dictionary<Tuple<string ,Type>, ICommand> commands = new Dictionary<Tuple<string ,Type>, ICommand>();

    public static void RegisterCommand(string commandName, ICommand command, Type type) {
        commands[new Tuple<string, Type>(commandName,type)] = command;
    }

    public static void Execute(string commandName, Type type) {
        commands[new Tuple<string, Type>(commandName,type)].Execute();
    }
}

Otherwise, all the same.

Second improvement

As a further evolution of the command, it would still set conditions on action execution. To do this, extend the class of Command. The condition will be given as an option. So we finish in the Command class property

public Func<bool> CanExecute { get; set;  }

Now you can change the Execute method and make use of a new property there.

public void Execute() {
    if(CanExecute() && action != null)
    action();
}

The third improvement

The logical development of all of this will have an opportunity to pass parameters to the command.

public class Command<T> : ICommand {
    public Action<T> Action { private get; set; }
    public Func<bool> CanExecute { private get; set; }

    private T parameter;

    public void SetParameter(object parameter) {
        this.parameter = (T) parameter;
    }

    public Command() {
        CanExecute = () => { return true; };
    }

    public void Execute() {
        if (CanExecute() && Action != null)
            Action(parameter);
    }
}

The command is now a generic class that can be applied to any type of parameters.

CommandManager changes, respectively. Now, before a call is transferred to the command will be an optional parameter.

public static void Execute(string commandName, Type type,object parameters = null) {
    var command = commands[new Tuple<string, Type>(commandName, type)];
    command.SetParameter(parameters);
    command.Execute();
}

In this case I used a new feature of the fourth framework, autoinitialization parameter. With this declaration the parameter can be optional, but the parameters of this type should always go after a set of mandatory parameters.

And as the test case (though degenerate in this case)

internal class MyClass {
    public MyClass() {
        var command = new Command<string> { Action = SomeAction };

        CommandManager.RegisterCommand(CommandNames.Open, command, GetType());

        CommandManager.Execute(CommandNames.Open, GetType());
        CommandManager.Execute(CommandNames.Open, GetType(), @"c:\temp\default.txt");
    }

    public void SomeAction(string s) {
        Console.Out.WriteLine("MC: " + s);
    }
}

If it is used in another class, it will be in this way

CommandManager.Execute(CommandNames.Open, typeof(MyClass), "from main thread");

Such the manager of the command would have to be on the idea in a previous article about interprocess communication.
Source code examples

Hard’n’heavy.

Tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>