2015-10-25 10 views
1

У меня есть расширение Visual Studio, которое включает в себя пакет и Tagger в том же VSIX.Расширяемость Visual Studio: как контролировать порядок загрузки компонентов?

Когда пакет загружен, он инициализирует несколько вещей, включая регистратор. Tagger использует регистратор. Все это работает для меня, но на одной клиентской машине Tagger загружается перед пакетом и падает, потому что регистратор еще не инициализирован.

Как выразить Visual Studio, что она должна всегда загружать пакет перед загрузкой Tagger?

Пакет выглядит следующим образом:

[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> 

Спасибо!

ответ

2

В вашем пакете имеется служба регистрации. Visual Studio имеет полную инфраструктуру для этого: How to: Provide a Service

Что вам нужно, в коде пакета, поэтому должен:

  1. создать некоторый интерфейс, который представляет договор на обслуживание (например, IMyLogger, например)

  2. регистр эта услуга (это будет в конечном итоге перейти в реестре во время установки так VS знает статический ваш пакет реализует это)

    [ProvideService(typeof(SMyLogger))] 
    public sealed class EntrianInlineWatchPackage : Package 
    {. . .}
  3. выполнить услугу (перейдите по ссылке выше для получения дополнительной информации).

Во всех других пакетов или расширений или расширений, которые будут использовать эту услугу (так в вашем коде Tagger), вы должны быть в состоянии get a reference to this service, например:

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

и волшебно, Visual Студия должна загрузить пакет, если это необходимо (благодаря параметрам реестра, объявленным через атрибут ProvideService).

PS: Обратите внимание, что это потребует, чтобы вы определили IMyLogger в сборке, доступной как в пакетах, так и в сборках Tagger. Или вы можете использовать хорошо известный интерфейс, который вам подходит.

+0

Это выглядит идеально, за исключением одного: как я могу называть 'GetService' перед загрузкой пакета? В моем текущем коде, когда что-то, кроме моего пакета (например, Tagger), нуждается в услуге, он вызывает метод «GetService» пакета, но все дело в том, что Tagger загружается перед пакетом, это сделать ...? – RichieHindle

+0

Вы не должны вызывать код своего пакета из кода Tagger (поэтому не вызывайте метод GetService вашего пакета оттуда).Проверьте 2-ую ссылку («Как получить услугу»): код метки не знает, кто реализует сервис SMyLogger, он запрашивает его, хотя стандартные методы VS (просто случается, что вы реализовали обе стороны, но это не имеет значения, это какой-то механизм интродукции зависимостей +, если вы это сделаете). –

+0

Я понимаю, что не делать. :-) Я не понимаю, что такое «ServiceProvider» в вашем примере? Когда я пытаюсь вызвать 'ServiceProvider.GetService()', я получаю «Требуется ссылка на объект», что кажется разумным - на каком объекте я должен называть «GetService»? (Я нахожу «ServiceProvider» в «Microsoft.VisualStudio.Shell» - это не тот?) – RichieHindle

 Смежные вопросы

  • Нет связанных вопросов^_^