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
因此,在包代码中,您需要的是:
创建一些表示服务契约的接口(例如 IMyLogger
)
注册此服务(这最终会在设置时进入注册表,以便 VS 以静态方式知道您的包实现了此服务)
[ProvideService(typeof(SMyLogger))]
public sealed class EntrianInlineWatchPackage : Package
{. . .}
实施服务(更多请参考上面的link)。
在将使用此服务的所有其他包或插件或扩展中(因此在您的 Tagger 代码中),您应该能够 get a reference to this service,例如:
IMyLogger logger = ServiceProvider.GetService(typeof(SMyLogger)) as IMyLogger;
而且,神奇的是,Visual Studio 应该在需要时加载包(感谢通过 ProvideService
属性声明的注册表设置)。
PS:请注意,这将要求您在 Package 和 Tagger 程序集都可以访问的程序集中定义 IMyLogger
。或者您可以使用适合您需要的众所周知的界面。
我有一个 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
因此,在包代码中,您需要的是:
创建一些表示服务契约的接口(例如
IMyLogger
)注册此服务(这最终会在设置时进入注册表,以便 VS 以静态方式知道您的包实现了此服务)
[ProvideService(typeof(SMyLogger))] public sealed class EntrianInlineWatchPackage : Package {. . .}
实施服务(更多请参考上面的link)。
在将使用此服务的所有其他包或插件或扩展中(因此在您的 Tagger 代码中),您应该能够 get a reference to this service,例如:
IMyLogger logger = ServiceProvider.GetService(typeof(SMyLogger)) as IMyLogger;
而且,神奇的是,Visual Studio 应该在需要时加载包(感谢通过 ProvideService
属性声明的注册表设置)。
PS:请注意,这将要求您在 Package 和 Tagger 程序集都可以访问的程序集中定义 IMyLogger
。或者您可以使用适合您需要的众所周知的界面。