使用EnvDTE以编程方式将函数添加到现有C#-file

时间:2012-11-14 10:21:20

标签: c# visual-studio-2010 envdte

我想以编程方式将函数(TestMethod)添加到现有的C#文件中。 经过一些谷歌搜索后,我找到了库EnvDTECodeModel.AddFunction - 方法,但我找不到我想要的好例子。

我想在新创建的函数中添加一个带有代码的函数,并且还有一个属性。像这样:

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

有人能告诉我一个如何做到这一点的例子吗?

编辑:我想编辑C#文件,就像编辑文本文件一样。我知道你可以用StreamWriter做到这一点,但有没有更好的方法呢?

1 个答案:

答案 0 :(得分:7)

EnvDTE可以成为现实。您可以开发VisualStudio加载项,然后修改Exec方法。在此方法中,您必须获取活动文档及其ProjectItem。在这里您可以找到包含大量CodeElements的CodeModel。在这些元素中,您必须找到CodeNamespace,并在此元素内部使用CodeClass。这是响应AddFunction的对象,返回可以添加属性和代码的新CodeFunction(这是我不太喜欢的部分,因为你必须使用EditPoint)。

这是一个非常简单的Exec版本,您可以将其作为起点:

    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();");
            }
        }
    }