Merq.VisualStudio 2.0.0

前缀已保留
dotnet add package Merq.VisualStudio --version 2.0.0                
NuGet\Install-Package Merq.VisualStudio -Version 2.0.0                
此命令旨在在Visual Studio的包管理器控制台中使用,因为它使用NuGet模块的Install-Package版本。
<PackageReference Include="Merq.VisualStudio" Version="2.0.0" />                
对于支持PackageReference的项目,将此XML节点复制到项目文件中,以引用包。
paket add Merq.VisualStudio --version 2.0.0                
#r "nuget: Merq.VisualStudio, 2.0.0"                
#r指令可用于F#交互式和Polyglot Notebooks。将其复制到交互式工具或脚本的源代码中,以引用包。
// Install Merq.VisualStudio as a Cake Addin
#addin nuget:?package=Merq.VisualStudio&version=2.0.0

// Install Merq.VisualStudio as a Cake Tool
#tool nuget:?package=Merq.VisualStudio&version=2.0.0                

此包提供了对Merq默认实现的MEF准备好的定制,这使得从使用Microsoft.VisualStudio.Composition的应用程序中消耗变得非常简单,以加载基于MEF的组件。

这是内置在Visual Studio中的,您可以通过在清单中将它声明为您扩展的先决条件,简单地通过项目来获取对Merq的依赖。

<PackageManifest Version="2.0.0" ...>
	<Prerequisites>
		<Prerequisite Id="Microsoft.VisualStudio.Component.Merq" Version="[17.0,)" DisplayName="Common Xamarin internal tools" />
	</Prerequisites>
</PackageManifest>

有了这些,您可以通过简单地将其导入到MEF组件中,来获得对IMessageBus的访问权限。

[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
class MyComponent
{
    readonly IMessageBus bus;
    
    [ImportingConstructor]
    public MyComponent(IMessageBus bus)
    {
        this.bus = bus;
        
        bus.Observe<OnDidOpenSolution>().Subscribe(OnSolutionOpened);
    }

    void OnSolutionOpened(OnDidOpenSolution e)
    {
        // do something, perhaps execute some command?
        bus.Execute(new MyCommand("Hello World"));

        // perhaps raise further events?
        bus.Notify(new MyOtherEvent());
    }
}

要将命令处理器导出到VS中,必须使用它们实现的相应接口导出,例如

public record OpenSolution(string Path) : IAsyncCommand;

[Export(typeof(IAsyncCommandHandler<OpenSolution>))]
public class OpenSolutionHandler : IAsyncCommandHandler<OpenSolution>
{
    public bool CanExecute(OpenSolution command) 
        => !string.IsNullOrEmpty(command.Path) && File.Exists(command.Path);
            
    public Task ExecuteAsync(OpenSolution command, CancellationToken cancellation)
    {
        // switch to main thread
        // invoke relevant VS API
    }
}

事件可以直接在总线上通知,如第一个示例所示,或者从外部产生。例如,OnDidOpenSolution的生产者看起来如下

public record OnDidOpenSolution(string Path);

[Export(typeof(IObservable<OnDidOpenSolution>))]
public class OnDidOpenSolutionObservable : IObservable<OnDidOpenSolution>, IVsSolutionEvents
{
    readonly JoinableTaskContext jtc;
    readonly Subject<OnDidOpenSolution> subject = new();
    readonly AsyncLazy<IVsSolution?> lazySolution;

    [ImportingConstructor]
    public OnDidOpenSolutionObservable(
        [Import(typeof(SVsServiceProvider))] IServiceProvider servideProvider,
        JoinableTaskContext joinableTaskContext)
    {
        jtc = joinableTaskContext;
        
        lazySolution = new AsyncLazy<IVsSolution?>(async () =>
        {
            await jtc.Factory.SwitchToMainThreadAsync();
            var solution = servideProvider.GetService<SVsSolution, IVsSolution>();
            solution.AdviseSolutionEvents(this, out var _);
            return solution;
        }, jtc.Factory);    
    }

    public IDisposable Subscribe(IObserver<OnDidOpenSolution> observer)
        => subject.Subscribe(observer);

    int IVsSolutionEvents.OnAfterOpenSolution(object pUnkReserved, int fNewSolution)
    {
        var path = jtc.Factory.Run(async () =>
        {
            if (await lazySolution.GetValueAsync() is IVsSolution solution &&
                ErrorHandler.Succeeded(solution.GetSolutionInfo(out var _, out var slnFile, out var _)) &&
                !string.IsNullOrEmpty(slnFile))
            {
                return slnFile;
            }

            return null;
        });

        if (path is string)
        {
            subject.OnNext(new OnDidOpenSolution(path));
        }

        return VSConstants.S_OK;
    }

    // rest of IVsSolutionEvents members
}

上面的实现只是一个示例,但不会太离谱地远离实际使用IVs* API的一个。但记住,消耗它有多简单是值得记住的。

[ImportingConstructor]
public MyComponent(IMessageBus bus)
{
    bus.Observe<OnDidOpenSolution>().Subscribe(OnSolutionOpened);
}

void OnSolutionOpened(OnDidOpenSolution e)
{
    // ...
}

外部生成器实现IObservable<T>的好处是,除非有人调用Observe<T>,否则根本不会实例化,这最大程度地降低了内置这种扩展机制的开销。

如果您在您的应用程序中部署 VS MEF,则适用相同的概念,因此应该是一个熟悉的过程。

产品 兼容的和额外的计算目标框架版本。
.NET Framework net472 兼容。 net48 已计算。 net481 已计算。
兼容目标框架
包含的目标框架(在包中)
了解更多关于目标框架.NET Standard的信息。

NuGet 包

此包没有被任何 NuGet 包使用。

GitHub 存储库

此包没有被任何流行 GitHub 存储库使用。

版本 下载 最后更新
2.0.0 136 1/29/2024
2.0.0-rc.6 47 1/29/2024
2.0.0-rc.5 48 1/27/2024
2.0.0-rc.3 85 7/10/2023
2.0.0-rc.2 75 7/10/2023
2.0.0-rc.1 79 7/7/2023
2.0.0-beta.4 77 7/6/2023
2.0.0-beta.3 92 11/19/2022
2.0.0-beta.2 94 11/18/2022
2.0.0-beta 127 11/16/2022
2.0.0-alpha 109 11/16/2022
1.5.0 371 2/16/2023
1.3.0 484 7/28/2022
1.2.0-beta 142 7/20/2022
1.2.0-alpha 144 7/16/2022