如何将我的服务注册为全局服务或者如何在我的场景中使用 MEF?

Gáb*_*kos 0 c# vsx vsix visual-studio-extensions visual-studio-2013

我想创建自己的具有全球知名度的服务。为了实现这一点,我遵循了这个示例解决方案。

一切顺利,我可以在一个类中调用我的服务,该类扩展自 Package 抽象类,如下所示:

public class ClientPackage : Package
{
   private void GetGlobalServiceCallback(object sender, EventArgs args)
   {
      IMyGlobalService service = GetService(typeof(SMyGlobalService)) as IMyGlobalService;
   }
}
Run Code Online (Sandbox Code Playgroud)

因为我在一个包中,所以我可以轻松调用 GetService 并且可以获得我的服务。但是,如果我想从一个不扩展 Package 抽象类的类获取服务,该怎么办?

例如,我有一个类,它实现了 ITagger 接口。如果我想获取此类中的服务,我必须以这种方式使用 Package.GetGlobalService() 方法:

var txtMgr = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
Run Code Online (Sandbox Code Playgroud)

我尝试使用 Package.GetGlobalServie() 获取自己的服务,但总是得到 null。链接的示例代码不包含我的问题的解决方案。

我可能错过了什么或者我在获得服务时遇到了错误的情况吗?

编辑:

好吧,假设我必须使用 MEF 来获取我的服务,因为我无法使用 Package.GetGlobalService() 获取我的服务。

我有一个包含 2 个项目的解决方案。一种是类库,其中包含这样的接口:

public interface INamesAccessor
{
    IEnumerable<string> GetNames();
}
Run Code Online (Sandbox Code Playgroud)

另一个项目是 VSPackage(与第一个项目有参考),它也实现了我的接口:

[Export(typeof(INamesAccessor))]
public sealed class BitbucketExtensionPackage : Package, INamesAccessor
{
    private IEnumerable<string> _names { get; set; }

    public IEnumerable<string> GetNames()
    {
        return _names;
    }
}
Run Code Online (Sandbox Code Playgroud)

假设如果用户单击“工具”菜单下的给定菜单,逻辑将设置名称的值。直到 _names 为空。

我想在我的提供商处使用此 _names 列表的内容,例如:

[Export(typeof(ITaggerProvider))]
[ContentType("text")]
[TagType(typeof(CommentTag))]
internal sealed class CommentTaggerProvider : ITaggerProvider
{
    [Import]
    public INamesAccessor _namesAccessor { get; set; }

    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
    {
        if (buffer == null)
            throw new ArgumentNullException("buffer");

        return buffer.Properties.GetOrCreateSingletonProperty(() => new CommentTagger(buffer, _namesAccessor )) as ITagger<T>;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里得到了namesAccessor,但每个字段都是空的,_names IEnumerable 也是如此。

当用户单击菜单按钮时,有没有办法强制 MEF 再次导入我的访问器?我做错了什么?

谢谢您的回答!:)

SLa*_*aks 5

您应该使用 MEF 为您的扩展编写服务;不是旧的基于 COM 的 ServiceProvider 的东西。

将所有实际代码放入 MEF 导出的类中,然后使用SComponentModel服务从包类中调用它们。

欲了解更多信息,请参阅我的博客