使用EnvDTE在现有的C#文件中编程添加函数

8
我想要通过编程将一个函数(TestMethod)添加到现有的C#文件中。 经过一些谷歌搜索,我找到了库EnvDTECodeModel.AddFunction方法,但我找不到想要的好示例。 我希望能够在新创建的函数中添加代码和属性。类似于这样的东西:
/// <summary>
/// Documentation
/// </summary>
[TestMethod]
public void TestMethod1()
{
    string test = Helper.CodeExample();
}

有人能给我展示一下如何做这个的示例吗?

编辑:我想编辑一个C#文件,就像你编辑文本文件一样。我知道可以使用StreamWriter来完成这个任务,但是是否有更好的方法呢?


你是指修改C#(文本)文件还是C#(.NET)类?修改文本与修改已编译代码完全不同。 - larsmoa
我的意思是一个C#文本文件。它用于生成测试文件。我可以使用StreamWriter来完成这个任务,但我认为可能有更好的方法来完成这个任务。 - Mathieu
你需要找到一个能够将代码解析成语法树的工具,然后修改该语法树以添加你的函数,并从该语法树生成一个新文件。 - Tamara Wijsman
Visual Studio可以为他完成这个任务(使用EnvDTE)。没必要重复造轮子 :-) - Francesco Baruchelli
1个回答

7

EnvDTE可能是最好的选择。您可以开发一个VisualStudio插件,然后修改Exec方法。在此方法中,您必须获取活动文档及其ProjectItem。这是您查找CodeModel的位置,其中包含许多CodeElements。在这些元素中,您必须找到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();");
            }
        }
    }

这正是我所期望的!这比仅仅像文本文件一样编辑cs文件要好得多。非常感谢! - Mathieu
1
这对我来说是一个很棒的起点!谢谢!还值得注意的是,能够使用SmartFormat而不是缩进。它会智能格式化从调用EditPoint开始到参数TextPoint结束的代码范围。以下是使用上述代码的示例: ep.Insert("string test = Helper.CodeExample();"); tp.CreateEditPoint().SmartFormat(ep); - philt5252

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接