Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically add function to existing C#-file with EnvDTE

I want to programmatically add a function (a TestMethod) to an existing C#-file. After some googling I have found the library EnvDTE and CodeModel.AddFunction-Method, but I can't find a good example of what I want.

I would like to add a function with code already in that newly created function and also with an attribute. Something like this:

/// <summary>
/// Documentation
/// </summary>
[TestMethod]
public void TestMethod1()
{
    string test = Helper.CodeExample();
}

Can anyone show me an example on how to do this?

EDIT: I want to edit a C# file, like you would edit a text-file. I know you could do this with a StreamWriter, but is there maybe a better way for doing this?

like image 648
Mathieu Avatar asked Nov 14 '12 10:11

Mathieu


1 Answers

EnvDTE can be the way to go. You can develop a VisualStudio Add-In and then modify the Exec method. In this method you have to get the active document and its ProjectItem. This is where you find the CodeModel which contains a lot of CodeElements. Among these elements you have to find the CodeNamespace, and inside this element the CodeClass. This is the object that responds to AddFunction returning the new CodeFunction to which you can add your attribute and the code (this is a part I don't like too much, since you have to use EditPoint).

This is a very simple version of Exec that you can use as a starting point:

    public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
    {
        handled = false;
        if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
        {
            handled = true;
            if (commandName == "TestAddMethod.Connect.TestAddMethod")
            {
                Document activeDoc = _applicationObject.ActiveDocument;
                if (activeDoc == null)
                    return;
                ProjectItem prjItem = activeDoc.ProjectItem;
                if (prjItem == null)
                    return;
                FileCodeModel fcm = prjItem.FileCodeModel;
                if (fcm == null)
                    return;

                CodeElements ces = fcm.CodeElements;
                // look for the namespace in the active document
                CodeNamespace cns = null;
                foreach (CodeElement ce in ces)
                {
                    if (ce.Kind == vsCMElement.vsCMElementNamespace)
                    {
                        cns = ce as CodeNamespace;
                        break;
                    }
                }
                if (cns == null)
                    return;
                ces = cns.Members;
                if (ces == null)
                    return;
                // look for the first class
                CodeClass cls = null;
                foreach (CodeElement ce in ces)
                {
                    if (ce.Kind == vsCMElement.vsCMElementClass)
                    {
                        cls = ce as CodeClass;
                        break;
                    }
                }
                if (cls == null)
                    return;
                CodeFunction cf = cls.AddFunction("TestMethod1", vsCMFunction.vsCMFunctionFunction, vsCMTypeRef.vsCMTypeRefVoid, -1, vsCMAccess.vsCMAccessPrivate);
                cf.AddAttribute("TestMethod", "true");
                TextPoint tp = cf.GetStartPoint(vsCMPart.vsCMPartBody);
                EditPoint ep = tp.CreateEditPoint();
                ep.Indent();
                ep.Indent();
                ep.Indent();
                ep.Insert("string test = Helper.CodeExample();");
            }
        }
    }
like image 135
Francesco Baruchelli Avatar answered Oct 03 '22 09:10

Francesco Baruchelli