Как асинхронно загрузить ModelingPackage (DSL-Tools) в Visual Studio 2019?

У меня есть проект DSL-tools, в котором я использую [ProvideAutoLoad], потому что он добавляет в Visual Studio набор команд меню, позволяющих пользователю преобразовывать код (у нас есть много текстовых шаблонов) и многое другое.

Поскольку VS2019 не позволяет чтобы больше не загружать пакеты синхронизации, я получаю эти раздражающие предупреждения, даже когда включена опция, разрешающая автозагрузку.

Очевидно, Microsoft не планирует предоставлять асинхронную версию ModelingPackage (я действительно начинаю сомневаться, не мешают ли они полностью отказаться от DSL-инструментов).

Кто-нибудь нашел способ обойти это?

Я попытался использовать другой пакет, построенный как AsyncPackage, чтобы один из них загрузил мой пакет DSL-tools на InitializeAsync(), но в итоге я получаю всевозможные исключения, использующие службу IVsShell.

protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<VSShell.ServiceProgressData> progress)
{
    // Default behavior

    await base.InitializeAsync(cancellationToken, progress).ConfigureAwait(false);

    // Load the service designer package

    this.EnsureDesignerPackage();

    // Switche to the UI thread

    await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

    // Menu commands

    this.InitializeMenuCommands();
}

private void EnsureDesignerPackage()
{
    // Package already loaded?

    if (!this.IsDesignerPackageLoaded())
    {
        this.LoadDesignerPackage();
    }
}

private bool IsDesignerPackageLoaded()
{
    // Package identifier

    Guid packageId = new Guid(GlobalConstants.ServiceDesignerPackageId);

    // Is loaded?

    IVsShell service = this.VsShellService;

    int hr = this.VsShellService.IsPackageLoaded(ref packageId, out IVsPackage package);
    if (ErrorHandler.Succeeded(hr) && package != null)
    {
        return true;
    }

    // Default result

    return false;
}

private void LoadDesignerPackage()
{
    // Package identifier

    Guid packageId = new Guid(GlobalConstants.ServiceDesignerPackageId);

    // Not loaded?

    int hr = this.VsShellService.IsPackageLoaded(ref packageId, out IVsPackage package);
    if (hr != VSConstants.S_OK || package == null)
    {
        // Load

        hr = this.VsShellService.LoadPackage(ref packageId, out package);
        if (ErrorHandler.Failed(hr))
        {
            string message = "Service designer loading failed: {0}.".Format().With(hr);
            this.ShowException(message);
        }
    }
}

person Hugo Quintela Ribeiro    schedule 22.08.2019    source источник
comment
ИМХО, инструменты DSL всегда были на грани отказа, с каждым выпуском VS ... Я не особо развивался все эти годы, он просто продолжает работать, потому что большинство VS по-прежнему поддерживают интерфейсы 20-летней давности. Я бы не стал делать ставку на это в долгосрочной перспективе, но вы должны спросить об этом Microsoft (почему бы не добавить комментарии в блог Мэдса Кристенсена)   -  person Simon Mourier    schedule 22.08.2019


Ответы (1)


Мне просто довелось провести клиента по этому же сценарию ранее сегодня. К сожалению, в прошлый раз, когда я спросил, в настоящее время нет планов по обновлению базовой структуры DSL для использования AsyncPackage или аналогичного. Я видел, что вы уже записали предложение в сайт сообщества разработчиков, и только что проголосовал и добавил свои собственные $ 0,02. Я бы посоветовал всем, кто нажмет на это, проголосовать за это предложение, указанное выше.

Чтобы добавить поддержку Async Load в объект DSL Package, вам нужно добавить ссылку на сборку Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dll, а затем отредактировать файл Package.tt, чтобы добавить VSShell. .PackageRegistration с параметром AllowsBackgroundLoading, установленным в значение true, и реализовать интерфейс IAsyncLoadablePackageInitialize в том же классе. Например:

namespace <#= CodeGenerationUtilities.GetPackageNamespace(this.Dsl) #>
{
    /// <summary>
    /// Double-derived class to allow easier code customization.
    /// </summary>
    [VSShell::ProvideMenuResource("1000.ctmenu", 1)]
    [VSShell::ProvideToolboxItems(1)]
    [VSShell::PackageRegistration(AllowsBackgroundLoading = true)]
    [global::Microsoft.VisualStudio.TextTemplating.VSHost.ProvideDirectiveProcessor(typeof(global::<#= this.Dsl.Namespace #>.<#= directiveName #>DirectiveProcessor), global::<#= this.Dsl.Namespace #>.<#= directiveName #>DirectiveProcessor.<#= directiveName #>DirectiveProcessorName, "A directive processor that provides access to <#= directiveName #> files")]
    [global::System.Runtime.InteropServices.Guid(Constants.<#= dslName #>PackageId)]
    internal sealed partial class <#= dslName #>Package : <#= dslName #>PackageBase, VSShellInterop.IAsyncLoadablePackageInitialize
    {
        public VSShellInterop.IVsTask Initialize(VSShellInterop.IAsyncServiceProvider pServiceProvider, VSShellInterop.IProfferAsyncService pProfferService, VSShellInterop.IAsyncProgressCallback pProgressCallback)
        {
            // do async initialization here
            return null;
        }
    }
}

Искренне,

person Ed Dore    schedule 24.08.2019
comment
Спасибо за идею! - person Hugo Quintela Ribeiro; 30.08.2019