Get the current filename from a Visual Studio text adornment extension

血红的双手。 提交于 2019-12-13 12:06:57

问题


I'm new to VS extension development. I'm currently working with the text adornment sample in VS 2015 and have been able to get coloured boxes showing correctly. Now I want to extend the sample so the adornment only appears on certain file names.

Googling has said I can use ITextDocumentFactoryService.TryGetTextDocument interface with the IWpfTextView.TextBuffer property to get a filename. This sounds great. But I can't seem to actually get the interface.

In my class I have:

    [Import]
    public ITextDocumentFactoryService TextDocumentFactoryService = null;

But it is always NULL.

How can I get ITextDocumentFactoryService?

namespace Test
{
    internal sealed class TestAdornment
    {
        [Import]
        public ITextDocumentFactoryService TextDocumentFactoryService = null;

        public TestAdornment(IWpfTextView view)
        {
        }

        /// <summary>
        /// Adds the scarlet box behind the 'a' characters within the given line
        /// </summary>
        /// <param name="line">Line to add the adornments</param>
        private void CreateVisuals(ITextViewLine line)
        {
            // TextDocumentFactoryService is NULL
        }
    }
}

回答1:


TextAdornmentTextViewCreationListener.cs

[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class TextAdornmentTextViewCreationListener : IWpfTextViewCreationListener
{
    [Import]
    public ITextDocumentFactoryService textDocumentFactory { get; set; }

    //...

    public void TextViewCreated(IWpfTextView textView)
    {
        new TextAdornment(textView, textDocumentFactory);
    }
}

TextAdornment.cs

internal sealed class TextAdornment
    {
        private readonly ITextDocumentFactoryService textDocumentFactory;
        private ITextDocument TextDocument;

        //...    

        public TextAdornment(IWpfTextView view, ITextDocumentFactoryService textDocumentFactory)
        {
            //...

            this.textDocumentFactory = textDocumentFactory;

            //...
        }

     internal void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
        {
            var res = this.textDocumentFactory.TryGetTextDocument(this.view.TextBuffer, out this.TextDocument);
            if (res)
            {
                //this.TextDocument.FilePath;
            }
            else
            {
                //ERROR
            }
        }
    }



回答2:


You got it via dependency injection.

As you only submitted 2 lines of code I suppose your context is set up, either explicitly by you, either implicitly by some environment who calls your code.

  • You should declare property instead of field
  • It should be public

Then automagically big brother will set it for you before you first access to it.

...or...

You can use constructor injection instead. Note: It is not you who will create your class.

private readonly ITextDocumentFactoryService _textDocumentFactoryService;

[ImportingConstructor]
internal YourClass(ITextDocumentFactoryService textDocumentFactoryService)
{
    _textDocumentFactoryService = textDocumentFactoryService;
}



回答3:


So in my case I needed to put the import statement into the AdornmentTextViewCreationListener. This implements IWpfTextViewCreationListener and is the one with the following decorating the class.

[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]

Then I can add

private readonly ITextDocumentFactoryService _textDocumentFactoryService;
[ImportingConstructor]

to my class



来源:https://stackoverflow.com/questions/33915010/get-the-current-filename-from-a-visual-studio-text-adornment-extension

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!