C# VisualStudio文本编辑器扩展

C# VisualStudio文本编辑器扩展,c#,visual-studio,visual-studio-2010,visual-studio-extensions,C#,Visual Studio,Visual Studio 2010,Visual Studio Extensions,我正在尝试开始使用VisualStudio(2010)扩展,但我很难找到合适的材料。我有SDK,但包含的示例似乎是装饰器、窗口和图标之类的东西 我正在尝试创建一个直接与文本编辑器配合使用的扩展(例如,按字母顺序排列类中的所有方法名,或使所有常量名大写),但我找不到这类功能的演示,甚至找不到教程 有人知道我在哪里可以找到这种东西吗?只要看看MSDN上的“编辑器扩展入门”网站就可以了 Thorsten我问了完全相同的问题,现在我已经浏览了几个小时的网页,直到我能够理解并解释您需要如何从这样一个扩展开

我正在尝试开始使用VisualStudio(2010)扩展,但我很难找到合适的材料。我有SDK,但包含的示例似乎是装饰器、窗口和图标之类的东西

我正在尝试创建一个直接与文本编辑器配合使用的扩展(例如,按字母顺序排列类中的所有方法名,或使所有常量名大写),但我找不到这类功能的演示,甚至找不到教程

有人知道我在哪里可以找到这种东西吗?

只要看看MSDN上的“编辑器扩展入门”网站就可以了


Thorsten

我问了完全相同的问题,现在我已经浏览了几个小时的网页,直到我能够理解并解释您需要如何从这样一个扩展开始

在下面的示例中,我们将创建一个小而哑的扩展名,当编辑完成后,它将始终在代码文件的开头添加“Hello”。这是非常基本的,但应该给你一个如何继续发展这个东西的想法

请注意:您必须完全自己解析代码文件-Visual Studio不会提供任何有关类、方法或其他内容的位置及其包含内容的信息。这是在使用代码格式化工具时要克服的最大障碍,本答案将不涉及这一点。[*]

对于跳过此答案的用户,请确保首先下载并安装了Visual Studio SDK,否则将找不到步骤1中提到的项目类型

创建项目

  • 首先创建一个类型为“Visual C#>Extensibility>VSIX project”的新项目(仅当您选择.NET Framework 4作为目标框架时可见)。请注意,您可能必须选择“编辑器分类器”项目类型而不是“VSIX项目”类型才能使其正常工作。评论如下

  • 创建项目后,将打开“source.extension.vsixmanifest”文件,使您能够设置产品名称、作者、版本、描述、图标等。我认为这一步非常自我解释,您可以现在关闭选项卡,稍后通过打开vsixmanifest文件来恢复它

  • 创建侦听器类以获得有关文本编辑器实例创建的通知

    接下来,我们需要在VisualStudio中创建文本编辑器时进行监听,并将我们的代码格式化工具绑定到它。VS2010中的文本编辑器是
    IWpfTextView
    的一个实例

  • 向我们的项目中添加一个新类,并将其命名为
    TextViewCreationListener
    。此类必须实现Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener接口。您需要在项目中添加对Microsoft.VisualStudio.Text.UI.Wpf的引用。程序集DLL位于VisualStudioIntegration\Common\Assemblies\v4.0下的Visual Studio SDK目录中

  • 您必须实现界面的
    TextViewCreated
    方法。此方法有一个参数,指定已创建的文本编辑器的实例。我们将创建一个新的代码格式化类,稍后将此实例传递给该类

  • 我们需要通过指定属性
    [Export(typeof(IWPTextViewCreationListener))]
    使
    TextViewCreationListener类对Visual Studio可见。将对System.ComponentModel.Composition的引用添加到项目的
    导出属性中

  • 此外,我们需要指定代码格式化程序应该绑定到文本编辑器的文件类型。我们只喜欢格式化代码文件,而不喜欢格式化纯文本文件,因此我们将属性
    [ContentType(“code”)]
    添加到listener类中。为此,您必须在项目中添加对Microsoft.VisualStudio.CoreUtility的引用

  • 此外,我们只想更改可编辑代码,而不想更改其周围的颜色或装饰(如示例项目中所示),因此我们将属性
    [TextViewRole(PredefinedTextViewRoles.editable)]
    添加到类中。同样,您需要一个新的参考,这次是Microsoft.VisualStudio.Text.UI

  • 将该类标记为内部密封。至少这是我的建议。现在,您的类应该与此类似:

    [ContentType("code")]
    [Export(typeof(IWpfTextViewCreationListener))]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal sealed class TextViewCreationListener : IWpfTextViewCreationListener
    {
        public void TextViewCreated(IWpfTextView textView)
        {
        }
    }
    
  • 创建用于代码格式化的类

    接下来,我们需要一个类来处理代码格式化逻辑、排序方法等。同样,在本例中,每当进行编辑时,只需在文件的开头添加“Hello”

  • 将名为
    Formatter
    的新类添加到项目中

  • 添加一个构造函数,该构造函数接受一个
    IWpfTextView
    参数。请记住,我们希望将创建的编辑器实例传递给侦听器类的
    TextViewCreated
    方法中的这个格式化类(只需将
    newformatter(textView);
    添加到该方法中)

  • 将传递的实例保存在成员变量中。在以后格式化代码时(例如检索插入符号位置),它会变得很方便。还要绑定编辑器实例的
    TextBuffer
    属性的
    Changed
    PostChanged
    事件:

    public Formatter(IWpfTextView view)
    {
        _view = view;
        _view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed);
        _view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged);
    }
    
  • 我们必须将
    PostChanged
    事件处理程序中的这个bool成员变量再次重置为
    false

  • 让我们将
    Changed
    事件的事件参数传递给我们的自定义
    FormatCode
    方法,因为它们包含上次编辑到现在之间发生的更改。这些编辑内容存储在数组
    e.Changes
    中,类型为
    INormalizedTextChangeCollection
    (如需有关此类型的详细信息,请参阅本文末尾的链接)。我们循环所有这些编辑,并使用此编辑生成的新文本调用自定义的
    HandleChange
    方法

    private void FormatCode(TextContentChangedEventArgs e)
    {
        if (e.Changes != null)
        {
            for (int i = 0; i < e.Changes.Count; i++)
            {
                HandleChange(e.Changes[0].NewText);
            }
        }
    }
    
  • 当康比
    private void FormatCode(TextContentChangedEventArgs e)
    {
        if (e.Changes != null)
        {
            for (int i = 0; i < e.Changes.Count; i++)
            {
                HandleChange(e.Changes[0].NewText);
            }
        }
    }
    
    private void HandleChange(string newText)
    {
        ITextEdit edit = _view.TextBuffer.CreateEdit();
        edit.Insert(0, "Hello");
        edit.Apply();
    }