VSIX扩展开发:ServiceProvider.GetService()调用报错求助
解决VSIX扩展中获取SVsStatusbar服务的类型推断错误
嘿,刚帮你排查了代码里的问题,这个报错其实是因为在VSIX的AsyncPackage环境下,获取服务的方式需要明确指定类型,而且你代码里的服务调用对象也有点问题。
问题根源
你写的ServiceProvider.GetService(typeof(SVsStatusbar))有两个问题:
- 这里的
ServiceProvider没有指向你扩展包的服务提供器,应该用构造函数里保存的this.package实例来获取服务; - 在现代VSIX开发(尤其是
AsyncPackage)中,GetService方法需要明确指定泛型类型参数,编译器没办法自动推断出你要获取的是IVsStatusbar接口。
修复方案
你可以用两种方式修改获取状态栏服务的代码:
方式1:同步获取(适合简单场景)
直接通过package实例调用泛型版的GetService,明确指定服务类型(SVsStatusbar)和要转换的接口类型(IVsStatusbar):
// 替换原来的错误行 IVsStatusbar statusBar = this.package.GetService<SVsStatusbar, IVsStatusbar>();
方式2:异步获取(更符合AsyncPackage设计,推荐)
因为你的包是AsyncPackage,官方更推荐异步获取服务。不过MenuItemCallback是同步方法,所以我们可以用GetAwaiter().GetResult()来等待异步操作完成:
// 替换原来的错误行 IVsStatusbar statusBar = this.package.GetServiceAsync<SVsStatusbar, IVsStatusbar>().GetAwaiter().GetResult();
修改后的完整回调代码
这里给你贴出修改后的MenuItemCallback,可以直接替换使用:
private void MenuItemCallback(object sender, EventArgs e) { // 用异步方式获取状态栏服务(推荐) IVsStatusbar statusBar = this.package.GetServiceAsync<SVsStatusbar, IVsStatusbar>().GetAwaiter().GetResult(); // 确保状态栏未冻结 int frozen; statusBar.IsFrozen(out frozen); if (frozen != 0) { statusBar.FreezeOutput(0); } // 设置状态栏文本 statusBar.SetText("We just wrote to the status bar."); // 冻结状态栏 statusBar.FreezeOutput(1); // 获取并弹出状态栏文本 string text; statusBar.GetText(out text); System.Windows.Forms.MessageBox.Show(text); // 解冻并清空状态栏 statusBar.FreezeOutput(0); statusBar.Clear(); }
额外提醒
如果你想更规范地适配异步场景,可以把MenuCommand换成AsyncMenuCommand,这样回调方法可以标记为async,避免用GetAwaiter().GetResult()阻塞UI线程,不过对于状态栏这种轻量操作,上面的修改已经足够解决问题啦。
内容的提问来源于stack exchange,提问作者Tanmay Bairagi
相关产品推荐
相关产品推荐

