服务基础知识
服务是两个 VSPackage 之间的协定。 一个 VSPackage 提供一组特定的接口,供另一个 VSPackage 使用。 Visual Studio 本身是 VSPackage 的集合,它为其他 VSPackage 提供服务。
例如,可以使用 SVsActivityLog 服务获取 IVsActivityLog 接口,该接口可用于写入活动日志。 有关详细信息,请参阅 如何:使用活动日志。
Visual Studio 还提供一些未注册的内置服务。 VSPackage 可以通过提供服务替代来替换内置或其他服务。 任何服务都只允许一个服务替代。
服务没有可发现性。 因此,必须知道要使用的服务的服务标识符(SID),并且必须知道它提供哪些接口。 服务的参考文档提供了此信息。
提供服务的 VSPackage 称为服务提供商。
提供给其他 VSPackage 的服务称为全局服务。
仅对实现它们的 VSPackage 或它创建的任何对象可用的服务称为本地服务。
替代其他包提供的内置服务或服务的服务称为服务替代。
服务或服务替代是按需加载的,也就是说,当服务提供的服务由另一个 VSPackage 请求时加载服务提供商。
为了支持按需加载,服务提供商将其全局服务注册到 Visual Studio。 有关详细信息,请参阅 “如何:提供服务”。
获取服务后,使用 QueryInterface (非托管代码)或强制转换(托管代码)获取所需的接口,例如:
托管代码按服务类型引用服务,而非托管代码按其 GUID 引用服务。
当 Visual Studio 加载 VSPackage 时,它将服务提供商传递给 VSPackage,以便向 VSPackage 授予对全局服务的访问。 这称为 VSPackage 的“坐” 。
VSPackage 可以是他们创建的对象的服务提供程序。 例如,窗体可能会将颜色服务的请求发送到其框架,该请求可能会将请求传递给 Visual Studio。
完全嵌套或不站点的托管对象可能要求 GetGlobalService 直接访问全局服务。
使用 GetGlobalService
有时,可能需要从工具窗口或控件容器获取服务,但尚未进行站点设置,或者已使用不知道所需服务的服务提供商进行站点。 例如,你可能想要从控件内部写入活动日志。 有关这些方案和其他方案的详细信息,请参阅 “如何:对服务进行故障排除”。
可以通过调用静态 GetGlobalService 方法来获取大多数 Visual Studio 服务。
GetGlobalService 依赖于在首次从包派生的任何 VSPackage 时初始化的缓存服务提供程序。 必须保证满足此条件,否则请为 null 服务做好准备。
幸运的是, GetGlobalService 大部分时间都正常工作。
如果 VSPackage 仅向另一个 VSPackage 提供已知服务,则请求服务的 VSPackage 将位于提供该服务的 VSPackage 加载之前。
如果工具窗口由 VSPackage 创建,则 VSPackage 将位于创建工具窗口之前。
如果控件容器由由 VSPackage 创建的工具窗口托管,则 VSPackage 将位于创建控件容器之前。
从工具窗口或控制容器中获取服务
在构造函数、工具窗口或控件容器中插入此代码:
IVsActivityLog log = Package.GetGlobalService(typeof(SVsActivityLog)) as IVsActivityLog; if (log == null) return;
此代码获取 SVsActivityLog 服务并将其转换为 IVsActivityLog 接口,该接口可用于写入活动日志。 有关示例,请参阅 如何:使用活动日志。