Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C#
Article

Generate properties automatically

Rate me:
Please Sign up or sign in to vote.
4.83/5 (17 votes)
2 May 20052 min read 120.2K   1.5K   46   40
An add-in for Visual Studio to generate properties automatically.

Image 1

Introduction

.NET introduces object oriented programming, which is why it became so popular. One of the object oriented programming concepts is Encapsulation. It brings clean code and it's for the best. But once you have defined your private members, you have to spend some awful time coding corresponding properties. I thought it would be interesting to accelerate the process and to automatically generate those properties. I did some research and I found around here some macros which would do the trick. However, I did think that it wasn't very productive and I thought that a right-click on a property would be easier. So I turned to Visual Studio add-ins...

Background

In order to develop some add-ins, Visual Studio allows us to use a wizard which makes the task easier. But it's not as simple as it should be, especially when you want to add some functionalities like contextual popup menu. I found a couple of articles which treated the subject, but each one concluded with the fact that MSDN wasn't that complete on the subject mostly because it was linked to Office.

Using the code

The source files contain two projects, one for the add-in, and one for the setup. In order to install the add-in correctly, you have to pass through the setup, or you can create a *.reg file to register it. The simplest way is to use the setup. As I work on Visual Studio .NET 2003, I don't know if it works on Visual Studio .NET 2002, but I think it would. Here is the OnConnection method which creates the buttons:

C#
public void OnConnection(object application, 
    Extensibility.ext_ConnectMode connectMode, object addInInst, 
                    ref System.Array custom)
{
    applicationObject = (_DTE)application;
    addInInstance = (AddIn)addInInst;
    if(connectMode == Extensibility.ext_ConnectMode.ext_cm_Startup)
    {
        object []contextGUIDS = new object[] { };
        Commands commands = applicationObject.Commands;
        _CommandBars commandBars = applicationObject.CommandBars;


        // When run, the Add-in wizard prepared the registry 
        // for the Add-in.
        // At a later time, the Add-in or its commands may 
        // become unavailable for reasons such as:
        //   1) You moved this project to a computer other 
        //        than which is was originally created on.
        //   2) You chose 'Yes' when presented with a message 
        //        asking if you wish to remove the Add-in.
        //   3) You add new commands or modify commands 
        //        already defined.
        // You will need to re-register the Add-in by building 
        //     the PropertyGeneratorSetup project,
        // right-clicking the project in the Solution Explorer, 
        //    and then choosing install.
        // Alternatively, you could execute the ReCreateCommands.reg 
        // file the Add-in Wizard generated in
        // the project directory, or run 'devenv /setup' from a command prompt.
        try
        {
             // Fetch parameters from registry
             prefix = Helper.GetRegistryValue(Helper.OPTION_PREFIX, 
                                            Helper.DEFAULT_PREFIX);
             getterSetterComment = 
                 Helper.GetRegistryValue(Helper.OPTION_GETTERSETTER_COMMENT, 
                 Helper.DEFAULT_GETTERSETTER_COMMENT);
             getterComment = 
                 Helper.GetRegistryValue(Helper.OPTION_GETTER_COMMENT, 
                 Helper.DEFAULT_GETTER_COMMENT);
             setterComment = 
                 Helper.GetRegistryValue(Helper.OPTION_SETTER_COMMENT, 
                 Helper.DEFAULT_SETTER_COMMENT);
             popupMenuEnabled = 
                 Boolean.Parse(Helper.GetRegistryValue(Helper.OPTION_POPUPMENU, 
                 Helper.DEFAULT_POPUPMENU));

             // Declare the commandBar which will hosts commands
             CommandBar cmbHost;

             // Fetch contextual menu from code editor
             CommandBar cmbCodeWindow = (CommandBar)commandBars["Code Window"];

             // Define commands text
             string libGetterSetter = "getter / setter";
             string libGetter = "getter";
             string libSetter = "setter";

             if (popupMenuEnabled)
             {
                 // In case of a popup menu, we have to add an invisible command 
                 // to force QueryStatus function to be called when 
                 // the user right clicks
                 Command cmdEnabler = commands.AddNamedCommand(addInInstance, 
                            "PropertyGeneratorEnabler", 
                            "", 
                            "", 
                            true, 
                            0, 
                            ref contextGUIDS, 
                            (int)vsCommandStatus.vsCommandStatusInvisible);
                 cmdEnabler.AddControl(cmbCodeWindow, 1);
    
                 // Create the popup menu
                 CommandBarPopup cbcPropertyGenerator = (CommandBarPopup)
                   cmbCodeWindow.Controls.Add(MsoControlType.msoControlPopup, 
                                                Missing.Value, 
                                                Missing.Value, 
                                                1, 
                                                true);
                 cbcPropertyGenerator.Visible = true;
                 cbcPropertyGenerator.BeginGroup = true;
                 cbcPropertyGenerator.Caption = "Generate property for...";

                 // Get the associated commandBar to add commands
                 cmbPropertyGenerator = cbcPropertyGenerator.CommandBar;

                // Copy reference
                cmbHost = cmbPropertyGenerator;
            }
            else
            {
                libGetterSetter = libGetterSetter + "Generate property for ";
                libGetter = libGetter + "Generate property for ";
                libSetter = libSetter + "Generate property for ";

                cmbHost = cmbCodeWindow;
            }

            // Add Getter, Setter and Getter/Setter commands
            Command cmdGetterSetter = commands.AddNamedCommand(addInInstance, 
                "PropertyGeneratorGetterSetter", 
                libGetterSetter, 
                "Generate property for Getter/Setter", 
                true, 
                6948, 
                ref contextGUIDS, 
                (int)vsCommandStatus.vsCommandStatusSupported + 
                     (int)vsCommandStatus.vsCommandStatusEnabled);
            cmdGetterSetter.AddControl(cmbHost, 1);
            Command cmdGetter = commands.AddNamedCommand(    addInInstance, 
                "PropertyGeneratorGetter", 
                libGetter, 
                "Generate property for Getter", 
                true, 
                6947, 
                ref contextGUIDS, 
                (int)vsCommandStatus.vsCommandStatusSupported+
                     (int)vsCommandStatus.vsCommandStatusEnabled);
            cmdGetter.AddControl(cmbHost, 2);
            Command cmdSetter = commands.AddNamedCommand(addInInstance, 
                "PropertyGeneratorSetter", 
                libSetter, 
                "Generate property for Setter", 
                true, 
                6943, 
                ref contextGUIDS, 
                (int)vsCommandStatus.vsCommandStatusSupported+
                     (int)vsCommandStatus.vsCommandStatusEnabled);
            cmdSetter.AddControl(cmbHost, 3);
        }
        catch(System.Exception e)
        {
            // Delete existing commands
            foreach(Command cmd in commands)
            {
                if ((cmd.Name != null) && 
                       (cmd.Name.StartsWith("PropertyGenerator")))
                    cmd.Delete();
            }

            // Show the message error
            MessageBox.Show("An error ocurred : " + 
              e.Message + "\r\n\nPropertyGenerator "+
              "has been cleaned. Please restart Visual Studio", 
              "PropertyGenerator error", 
              MessageBoxButtons.OK, 
              MessageBoxIcon.Error);
        }
    }
}

PropertyGenerator creates buttons at Visual Studio startup and deletes them on Visual Studio stop. It's easier this way to control the add-in than to create them on setup.

Here is the code that generates the property:

C#
private void GenerateProperty(PropertyTypeValue propertyType)
{
    string propType = "";
    string propName = "";
    string propVariable = "";
    string prop = "";

    try
    {                
        // Fetch informations to generate the property
        FormatParameters(prefix, ref propType, 
                    ref propName, ref propVariable);

        // Get current selection
        TextSelection txsSelection = 
            (TextSelection)applicationObject.ActiveDocument.Selection;

        // Go to the end of line
        txsSelection.EndOfLine(false);

        // Jump 2 lines
        txsSelection.NewLine(2);

        // Generate property
        switch(propertyType)
        {
            case PropertyTypeValue.GetterSetter :
                prop = String.Concat(    "/// <SUMMARY>\r\n/// ", 
                                        getterSetterComment, 
                                        " \r\n/// </SUMMARY>\r\npublic ", 
                                        propType, 
                                        " ", 
                                        propName, 
                                        " {\r\nget\r\n{\r\nreturn ", 
                                        propVariable, 
                                        ";\r\n}\r\nset\r\n{\r\n", 
                                        propVariable, 
                                        " = value;\r\n}\r\n}");
                break;
            case PropertyTypeValue.Getter :
                prop = String.Concat(    "/// <SUMMARY>\r\n/// ", 
                                        getterComment, 
                                        " \r\n/// </SUMMARY>\r\npublic ", 
                                        propType, 
                                        " ", 
                                        propName, 
                                        " {\r\nget\r\n{\r\nreturn ", 
                                        propVariable, 
                                        ";\r\n}\r\n}");
                break;
            case PropertyTypeValue.Setter :
                prop = String.Concat(    "/// <SUMMARY>\r\n/// ", 
                                        setterComment, 
                                        " \r\n/// </SUMMARY>\r\npublic ", 
                                        propType, 
                                        " ", 
                                        propName, 
                                        " {\r\nset\r\n{\r\n", 
                                        propVariable, 
                                        " = value;\r\n}\r\n}");
                break;
        }

        // Insert into the code
        txsSelection.Insert(prop, 
                (int)vsInsertFlags.vsInsertFlagsInsertAtEnd);

        // Go to the start of line
        txsSelection.StartOfLine(
            vsStartOfLineOptions.vsStartOfLineOptionsFirstText, true);

        // Format code
        txsSelection.SmartFormat();

        // Go to the end of comment
        txsSelection.GotoLine(txsSelection.TopPoint.Line + 1, false);
        txsSelection.EndOfLine(false);
    }
    catch(Exception)
    {
        throw;
    }
}

I did an Options tab to set some parameters:

Options tab

They are stored in the registry, that's why you have to use the setup to create useful keys. You can parameter the prefix, automatic comments, and you can choose if you want the buttons in a popup menu or not. To add an Options tab, you have to create a UserControl class that implements the IDTToolsOptionsPage interface.

Points of Interest

I hope this little add-in will help some guys. I believe there're some interesting concepts in here like Option tabs popup menus:

Popup menu

History

  • 01/07/2005 - Version 1.0.0
  • 02/09/2005 - Version 1.1.0:
    • Main bug correction for property generation.
    • Contextual labels correction.
    • Prefix size optimization (thanks to Olivier).
  • 02/09/2005 - Version 1.2.0:
    • Bug correction for members without visibility (caught by vasiletomoiaga).
  • 02/11/2005 - Version 1.3.0:
    • Bug in the Options tab (caught by Stefan).
  • 26/04/2005 - Version 1.4.0:
    • Use summary from the member as comment for the property (thanks to Bjørnar Sundsbø).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRequest to port this nice tool to Visual Studio 2005 Pin
ProgrammerGurdev11-Dec-07 5:23
ProgrammerGurdev11-Dec-07 5:23 
GeneralRe: Request to port this nice tool to Visual Studio 2005 Pin
Dieter_Van_Vaalwater13-May-08 10:03
Dieter_Van_Vaalwater13-May-08 10:03 
GeneralRe: Request to port this nice tool to Visual Studio 2005 Pin
Franck Desbrosses13-May-08 21:50
Franck Desbrosses13-May-08 21:50 
GeneralRe: Request to port this nice tool to Visual Studio 2005 Pin
Roberto Guerzoni26-Oct-10 5:27
professionalRoberto Guerzoni26-Oct-10 5:27 
QuestionHow to enable in VS2005 Pin
skov_k19-Dec-06 23:52
skov_k19-Dec-06 23:52 
GeneralBuilt in to Visual Studio 2005 Pin
bijobijo13-Apr-06 19:20
bijobijo13-Apr-06 19:20 
GeneralRe: Built in to Visual Studio 2005 Pin
Franck Desbrosses17-Apr-06 23:04
Franck Desbrosses17-Apr-06 23:04 
GeneralRe: Built in to Visual Studio 2005 Pin
ed welch11-Mar-08 6:05
ed welch11-Mar-08 6:05 
GeneralThanks Pin
What About Thad?18-Jan-06 6:18
What About Thad?18-Jan-06 6:18 
GeneralArray index error - Bug fix Pin
W3sty26-Oct-05 3:43
W3sty26-Oct-05 3:43 
GeneralArray index error Pin
Roy Higgs18-Jul-05 20:45
Roy Higgs18-Jul-05 20:45 
GeneralRe: Array index error Pin
Roy Higgs18-Jul-05 20:48
Roy Higgs18-Jul-05 20:48 
GeneralRe: Array index error Pin
Franck Desbrosses18-Jul-05 21:11
Franck Desbrosses18-Jul-05 21:11 
GeneralIs it possible to... Pin
wallabou8-May-05 11:31
wallabou8-May-05 11:31 
GeneralRe: Is it possible to... Pin
Franck Desbrosses8-May-05 11:50
Franck Desbrosses8-May-05 11:50 
GeneralRe: Is it possible to... Pin
Ajek13-Jun-05 21:30
Ajek13-Jun-05 21:30 
General...Custom option pages not shown Pin
klincky16-Mar-05 3:06
klincky16-Mar-05 3:06 
GeneralRe: ...Custom option pages not shown Pin
Franck Desbrosses16-Mar-05 3:16
Franck Desbrosses16-Mar-05 3:16 
GeneralPop Menu don't show Pin
punk_ssa11-Mar-05 8:48
punk_ssa11-Mar-05 8:48 
GeneralRe: Pop Menu don't show Pin
Franck Desbrosses16-Mar-05 3:20
Franck Desbrosses16-Mar-05 3:20 
GeneralDoes not work if several space char Pin
fbuff18-Feb-05 1:26
fbuff18-Feb-05 1:26 
GeneralRe: Does not work if several space char Pin
Franck Desbrosses18-Feb-05 1:45
Franck Desbrosses18-Feb-05 1:45 
GeneralRe: Does not work if several space char Pin
W3sty27-Oct-05 6:32
W3sty27-Oct-05 6:32 
GeneralRe: Does not work if several space char Pin
Franck Desbrosses27-Oct-05 6:39
Franck Desbrosses27-Oct-05 6:39 
GeneralLittle bug saving the options... Pin
Stefan Born10-Feb-05 23:46
Stefan Born10-Feb-05 23:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.