Visual Studio 扩展性:如何控制组件的加载顺序?

Visual Studio Extensibility: How to control the loading order of components?

我有一个 Visual Studio 扩展,它在同一个 VSIX 中包含一个包和一个标记器。

加载包时,它会初始化一些东西,包括记录器。标记器使用记录器。这一切对我都有效,但在一台客户机器上,标记器在包之前加载,并且由于记录器尚未初始化而崩溃。

我如何向 Visual Studio 表达它应该始终在加载标记器之前加载包?

包裹看起来像这样:

[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)]
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)]
public sealed class EntrianInlineWatchPackage : Package ...

标记器看起来像这样:

[Export(typeof(IViewTaggerProvider))]
[ContentType("C/C++")]
[TextViewRole(PredefinedTextViewRoles.Document)]
[TagType(typeof(ValueTag))]
public class ValueTaggerProvider : IViewTaggerProvider
{
    [Import]
    internal IClassifierAggregatorService AggregatorService;

    public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
    {
        ...
        return buffer.Properties.GetOrCreateSingletonProperty("com.entrian.ValueTagger", delegate () {
            IClassifier classifier = AggregatorService.GetClassifier(buffer);
            return new ValueTagger(classifier, textView, buffer) as ITagger<T>;
        }) as ITagger<T>;

vsixmanifest 如下所示:

<Content>
  <VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>
  <MefComponent>|%CurrentProject%|</MefComponent>
</Content>

谢谢!

您的包裹提供了日志记录服务。 Visual Studio 拥有完整的基础设施:How to: Provide a Service

因此,在包代码中,您需要的是:

  1. 创建一些表示服务契约的接口(例如 IMyLogger

  2. 注册此服务(这最终会在设置时进入注册表,以便 VS 以静态方式知道您的包实现了此服务)

    [ProvideService(typeof(SMyLogger))]
    public sealed class EntrianInlineWatchPackage : Package
    {. . .}
  3. 实施服务(更多请参考上面的link)。

在将使用此服务的所有其他包或插件或扩展中(因此在您的 Tagger 代码中),您应该能够 get a reference to this service,例如:

IMyLogger logger = ServiceProvider.GetService(typeof(SMyLogger)) as IMyLogger;

而且,神奇的是,Visual Studio 应该在需要时加载包(感谢通过 ProvideService 属性声明的注册表设置)。

PS:请注意,这将要求您在 Package 和 Tagger 程序集都可以访问的程序集中定义 IMyLogger。或者您可以使用适合您需要的众所周知的界面。