During my days of working with Visual Studio Packages we have on work come up with a “Command Pattern” for binding menu items defined in the .vsct files to classes so they are easier to work with.

It’s not a fully elaborated Command Pattern where you bind the commands together in a “string” of commands enabling you to go back and regret your actions, instead it just helps to isolate the implementation of each menu item.

First some simple basics.

ICommand

The ICommand interface is implemented for all commands so we are able to generalize all implemented commands.

   1:  public interface ICommand
   2:  {
   3:      void Execute( object sender, EventArgs args );
   4:  }

CommandAttribute

The Command Attribute class is used to define the binding between the implemented command class and an item defined in the .vsct file, the class is used as a C# attribute on all command classes.

   1:  public class CommandAttribute : Attribute
   2:  {
   3:      public int CommandId { get; private set; }
   4:      public Guid CommandSet { get; private set; }
   5:   
   6:      public CommandAttribute( int commandId, string commandSet )
   7:      {
   8:          CommandId = commandId;
   9:          CommandSet = new Guid(commandSet);
  10:      }
  11:  }

CommandController

The CommandController is what actually binds the implementation together with the .vsct file, what it does is, when ever the "RegisterCommand<T>” method is called, it creates a new instance of they type supplied, digs out the “CommandAttribute” from the type and then uses the attribute to bind it to a defined menu item in the usual VSX way.

   1:  public class CommandController
   2:  {
   3:      private readonly IMenuCommandService mcs;
   4:   
   5:      public CommandController(IMenuCommandService mcs)
   6:      {
   7:          this.mcs = mcs;
   8:      }
   9:   
  10:      public void RegisterCommand<T>() where T : ICommand, new()
  11:      {
  12:          ICommand command = Activator.CreateInstance<T>();
  13:   
  14:          Type type = typeof(T);
  15:          object[] commandInfo = type.GetCustomAttributes(typeof(CommandAttribute), false);
  16:          if(commandInfo.Length > 0)
  17:          {
  18:              CommandAttribute attribute = commandInfo[0] as CommandAttribute;
  19:              if (attribute != null)
  20:              {
  21:                  CommandID commandID = new CommandID(attribute.CommandSet, attribute.CommandId);
  22:                  MenuCommand menuCommand = new MenuCommand(command.Execute, commandID);
  23:                  mcs.AddCommand(menuCommand);
  24:                  return;
  25:              }
  26:          }
  27:          throw new ArgumentException("Type "+typeof(T).FullName+"did not have an CommandAttribute attached.");
  28:      }
  29:  }

Usage

Now instead of having all the Guids and Id’s that correspond to an item in the .vsct file in a huge “Constant” file, they are now defined closer to the code they actually executes. The constant file does not hurt if to use in this scenario either, as such you can see the guid for the command set is fetched from that still.

   1:  [Command(0x101, GuidList.GUID_COMMAND_SET)]
   2:  public class MyCommand : ICommand
   3:  {
   4:      public void Execute(object sender, EventArgs e)
   5:      {
   6:          MessageBox.Show("Hello fom MyCommand");
   7:      }
   8:  }

 

Within the Initialize method of the Package class (where you inherit from “ProjectPackage”) the following lines of code is used to registering the actual commands.

   1:  IMenuCommandService mcs = GetService<IMenuCommandService>();
   2:  if ( null != mcs )
   3:  {
   4:      CommandController controller = new CommandController(mcs);
   5:      controller.RegisterCommand<MyCommand>();
   6:      //... more register calls.
   7:  }

 

I choose to keep command controller and usage explicit, but in reality the registration of these bindings could easily have been automated, this could be done using castle for registering them in or another way.

Another thing to note if you start using castle, is that you can suddenly use castle to initialize the command objects as well, allowing them to have dependencies.

In any case, your commands will be likely to depend of the DTS interface for some stuff, there is several ways to get around this without castle, what we did at first was adding an interface to our package implementation exposing 2 methods.

   1:   public interface IPackageService
   2:   {
   3:      T GetToolWindow<T>(int id, bool create) where T : ToolWindowPane;
   4:      T GetService<T>();
   5:  }

And then added that as a Property to the ICommand interface as well as passing it to the CommandController, now the ICommand interface looks as:

   1:  public interface ICommand
   2:  {
   3:      IPackageService PackageService { get; set; }
   4:      void Execute(object sender, EventArgs e);
   5:  }

 

And when we create a new command in the command controller, we instantly after sets the PackageService property.

   1:  ICommand command = Activator.CreateInstance<T>();
   2:  command.PackageService = service;

 

This is not ideal, it would be better to provide it in the constructor of the command, however this gives a sort of hidden requirement to the implementation, using castle or any other kind of IoC/DI would make for a better solution here, but for now I wanted to keep it simple.

Next ill talk some about a few notifications we can get from Visual Studio, one in particular that will allow us to wait with initialization if we so happens to need the DTS interface during that.