C# 如何在VS2019扩展(MEF)中获取活动的IWpfTextView

C# 如何在VS2019扩展(MEF)中获取活动的IWpfTextView,c#,visual-studio-2019,mef,visual-studio-extensions,C#,Visual Studio 2019,Mef,Visual Studio Extensions,我正在尝试在VS2019扩展中获取活动的C#编辑器IWpfTextView。我正在使用一个小型MEF服务将视图注入到VSAsyncPackage中。但它不是很可靠-有时注入的视图是错误的(例如,从另一个视图)或丢失的。服务内容如下: 公共接口IActiveViewAccessor { IWpfTextView?活动视图{get;} } [导出(类型(IWPTextViewConnectionListener))] [导出(类型(IActiveViewAccessor))] [内容类型(“文本”)

我正在尝试在VS2019扩展中获取活动的C#编辑器IWpfTextView。我正在使用一个小型MEF服务将视图注入到VSAsyncPackage中。但它不是很可靠-有时注入的视图是错误的(例如,从另一个视图)或丢失的。服务内容如下:

公共接口IActiveViewAccessor
{
IWpfTextView?活动视图{get;}
}
[导出(类型(IWPTextViewConnectionListener))]
[导出(类型(IActiveViewAccessor))]
[内容类型(“文本”)]
[TextViewRole(预定义的textViewRoles.Document)]
内部密封类ActiveViewConnectionListener:IWpfTextViewConnectionListener,IActiveViewAccessor
{
公共IWPTextView?活动视图{get;私有集;}
public void subjectBuffers已连接(IWPTextView textView、ConnectionReason、Collection subjectBuffers)
{
this.ActiveView=textView;
}
public void subjectBuffers断开连接(IWPTextView textView、ConnectionReason、Collection subjectBuffers)
{
this.ActiveView=null;
}
}
此服务将作为以下内容注入VSPackage:

this.viewAccessor=this.exportProvider.GetExportedValue();
它被用作:

var view=this.viewAccessor?.ActiveView;
有没有更好、更稳定的方法可以在异步VSPackage中获取IWpfTextView

到目前为止,这里有一些相关的问题,但并不完全是我所期望的:


  • 经过一点调试和探索,我认为我最初的方法非常幼稚。因为在一个简单的情况下,
    IWpfTextViewConnectionListener在每个编辑器窗口中只触发一次,并且在已经连接的视图之间切换时不会触发

    在使用它进行实验并潜入系统后,我将
    IActiveViewAccessor
    更改为:

    公共接口IActiveViewAccessor
    {
    IWpfTextView?活动视图{get;}
    }
    [导出(类型(IActiveViewAccessor))]
    内部密封类ActiveViewAccessor:IActiveViewAccessor
    {
    专用只读SVsServiceProvider服务提供商;
    专用只读IVSEditorAdapterFactoryService编辑器适配器FactoryService;
    [导入构造函数]
    公共ActiveViewAccessor(
    SVsServiceProvider vsServiceProvider,
    IVSEditor适配器工厂服务编辑器适配器工厂服务)
    {
    this.serviceProvider=vsServiceProvider;
    this.editorAdaptersFactoryService=editorAdaptersFactoryService;
    }
    公共IWpfTextView?活动视图
    {
    得到
    {
    IVsTextManager2文本管理器=
    serviceProvider.GetService();
    if(textManager==null)
    {
    返回null;
    }
    int hr=textManager.GetActiveView2(
    fMustHaveFocus:1,
    pBuffer:null,
    grfIncludeViewFrameType:(uint)\u VIEWFRAMETYPE.vftdewindow,
    ppView:out-IVsTextView-vsTextView);
    if(ErrorHandler.Failed(hr))
    {
    返回null;
    }
    返回editorAdaptersFactoryService.GetWpfTextView(vsTextView);
    }
    }
    }
    
    经过一点调试和探索,我认为我最初的方法非常幼稚。因为在一个简单的情况下,
    IWpfTextViewConnectionListener在每个编辑器窗口中只触发一次,并且在已经连接的视图之间切换时不会触发

    在使用它进行实验并潜入系统后,我将
    IActiveViewAccessor
    更改为:

    公共接口IActiveViewAccessor
    {
    IWpfTextView?活动视图{get;}
    }
    [导出(类型(IActiveViewAccessor))]
    内部密封类ActiveViewAccessor:IActiveViewAccessor
    {
    专用只读SVsServiceProvider服务提供商;
    专用只读IVSEditorAdapterFactoryService编辑器适配器FactoryService;
    [导入构造函数]
    公共ActiveViewAccessor(
    SVsServiceProvider vsServiceProvider,
    IVSEditor适配器工厂服务编辑器适配器工厂服务)
    {
    this.serviceProvider=vsServiceProvider;
    this.editorAdaptersFactoryService=editorAdaptersFactoryService;
    }
    公共IWpfTextView?活动视图
    {
    得到
    {
    IVsTextManager2文本管理器=
    serviceProvider.GetService();
    if(textManager==null)
    {
    返回null;
    }
    int hr=textManager.GetActiveView2(
    fMustHaveFocus:1,
    pBuffer:null,
    grfIncludeViewFrameType:(uint)\u VIEWFRAMETYPE.vftdewindow,
    ppView:out-IVsTextView-vsTextView);
    if(ErrorHandler.Failed(hr))
    {
    返回null;
    }
    返回editorAdaptersFactoryService.GetWpfTextView(vsTextView);
    }
    }
    }
    
    我建议您可以添加关于您的提示的答案,而不是在问题中。@PerryQian MSFT我不完全确定访问活动IWpfTextView的“现代”或“正确”方式,但您的建议很有意义,谢谢。完成。我建议您可以添加有关提示的答案,而不是在问题中。@PerryQian MSFT我不完全确定访问活动IWpfTextView的“现代”或“正确”方式,但您的建议是有意义的,谢谢。完成。