![]() |
General Programming »
Macros and Add-ins »
VS.NET Add-ins
Intermediate
Building a Refactoring Plug-in for VS.NET - the SequelBy Stephan MeynDescribes how to extend the original refactor add-in with additional features. |
C#, Windows, .NET 1.0, .NET 1.1VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

Based on an existing add-in, this article shows a simple framework for creating add-ins that provide multiple refactoring functions. It shows how to interact with the source code model, automating editing functions in the source, and generating new classes.
A year ago, I wrote an article that provided a Visual Studio add-in to refactor a variable into a property. Since then this add-in has been in general use in my work and I have added several other refactoring functions. To this purpose, I implemented a little framework for my add-ins to make it easier to add other refactoring functions.
The add-in now sports the following features:
CollectionBase).
When you create a new project to build a VS plug-in, VS.NET generates a class
called connect. This class contains all the necessary interfaces
that will be called by VS.NET. There are three kinds of calls:
You do not need to have one connect class per command, however if
you make multiple ones available in this class (as is done here), the connect
call has to work out which command is affected in the Query and Exec calls.
The plug-in framework solves this by creating a base class called VS-Plugin.
Each kind of command listed above is implemented as a sub class of VS-Plugin.
The connect class is now only aware of a collection of these
plug-ins, and when a Query or Exec call comes, it simply iterates through its
collection and passes the request on to the appropriate class.

The VSPlugIn class also contains several utility functions to do
things such as:
Most plug-ins also have a separate class to do the actual work - e.g., the MakeMockObject
plug-in class has a class called MockObjectBuilder. This is simple
common sense of separating concerns, the plug-in class' purpose is to
understand the request's detail and to deliver the resulting code into the
right place, the MockObjectBuilder class' purpose is to generate
the Mock class.
There are only a few steps that need to be done:
VSPlugIn has several abstract properties and methods which you must
implement:
cmdName: the short command, e.g.: "MakeProperty".
qualifiedName: the fully qualified command, e.g.: "RefactorAddIn.Connect.MakeProperty".
IconId: the ID of the icon to show in the menu, e.g.: 54.
position: where in the menu to position the command (1=
first).
shortDescription: the text to show in the menu.
Description: the text for the tool help.
doQueryStatus(): implement the logic to determine if the
method currently makes sense and should be active or be inactive (or
invisible).
doExec(): implement the actual action of the command.
The connect class has a method called OnStartupComplete.
You must add your plug-in to the other plug-in's collection and call the
methods to have it show up in the right tool bars.
CommandBar popup = InsertSubMenu("Code Window", "Refactoring");
CommandBar classViewCommandBar = applicationObject.CommandBars["Class View Item"];
VSPlugIn plugin = new PropertyMaker(applicationObject, addInInstance);
Plugins.Add(plugin);
plugin.InsertCommand(classViewCommandBar,false);
plugin.InsertCommand(popup, false);
The first two lines are already given, they provide two commandbars, one a separate popup menu that is part of the Code Window menu (the one that pops up when you right click in the code window), and the other is the menu that pops up when you right click in the Class Explorer.
You need to add code in similar to the last four lines shown above:
InsertCommand
method. The boolean should only be true for special circumstances when
developing - see below in Points of Interest.
The above example makes the property maker available on both menus. You can target other menubars or leave them out altogether. In this instance, you can still bind to your command via the keyboard mapping available in the Tools->Options dialog (select Folder Environment and item Keyboard) - or you can call your command from macros.
Programming Visual Studio.NET is not for the faint hearted. Good documentation is not easy to come by. However, I found the book "Inside Microsoft Visual Studio. NET" (Brian Johnson, Craig Skibo, Marc Young, Microsoft Press, ISBN 0-7356-1874-7) to be an excellent help. Still you need to read it several times.
Visual Studio .NET is written in COM, which makes life less pleasant. Here are a few pointers:
protected bool HasCommand(string commName,out Command command)
{
command = null;
try
{
Commands commands = _applicationObject.Commands;
command = commands.Item(commName,-1);
return true;
}
catch (System.Exception){}
return false;
}
InsertClass, which inserts a new class into the code model, only
works with C++, not for C# or VB.NET. However, InsertMethod
does.
CollectionBuilder
class for an example.
VSPlugIn::InsertCommand method has a
boolean parameter called deleteIfExists; if true, it will
delete existing commands before creating a new one. This parameter should only
be true during developing and debugging your add-in. In default mode (=false),
it will try to find and use the existing command and create one only if it
doesn't exist yet.
InsertCommand
method tries to flush these out by calling flushControls(). If you
don't do this, all kinds of weird things can happen, sending you around the
bend.
HKEY_CURRENTUSER\ Software\ MethodsConsulting\ RefactorAddIn\ PrivatevarCase. Possible values are:
Enjoy
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 31 Aug 2004 Editor: Nishant Sivakumar |
Copyright 2004 by Stephan Meyn Everything else Copyright © CodeProject, 1999-2009 Web09 | Advertise on the Code Project |