如何将DevForce Punch集成到Visual Studio 2017内部Composition Container?
我来帮你搞定VSIX和Cocktail容器集成的问题!你的核心痛点是VS用自己独立的MEF容器,导致Cocktail的容器和VS的容器无法互通,进而MEF导出不被识别。下面是具体的实现步骤和代码示例:
解决步骤
1. 获取VS内部的MEF组合容器
你已经拿到了DTE和ServiceProvider的引用,接下来要通过它们获取VS的核心MEF容器:
// 从ServiceProvider获取VS的ComponentModel服务 var componentModel = (IComponentModel)sp.GetService(typeof(SComponentModel)); // 拿到VS默认的组合容器 var vsCompositionContainer = componentModel.DefaultCompositionContainer;
这里的SComponentModel是VS暴露自身MEF容器的关键服务,通过它就能拿到VS内部管理所有扩展性部件的容器实例。
2. 将VS容器集成到Cocktail的容器体系
Cocktail的CompositionHost支持两种方式集成外部容器,根据你的需求选一种即可:
方式一:把VS容器作为外部依赖容器
这种方式下Cocktail会保留自己的容器,但会优先从VS容器中解析服务,适合需要同时管理自有部件和VS服务的场景:
// 创建Cocktail容器配置 var config = new CompositionHostConfiguration(); // 添加VS容器作为外部容器 config.AddExternalContainer(vsCompositionContainer); // 初始化Cocktail宿主 var cocktailHost = CompositionHost.Initialize(config);
方式二:直接复用VS容器作为Cocktail的宿主
这种方式更适合VSIX场景,因为所有部件都直接在VS的容器中管理,能确保你的MEF导出被VS正确识别:
// 直接用VS的容器初始化Cocktail宿主 var cocktailHost = new CompositionHost(vsCompositionContainer);
3. 注册你的自定义MEF部件
不管用哪种方式,最后都要把你VSIX里的MEF导出部件注册到容器中:
// 组合当前类中的MEF导出(如果你的Package类有导出的话) cocktailHost.ComposeParts(this); // 如果有其他独立的MEF部件,也可以这样注册 // cocktailHost.ComposeParts(new MyCustomExportedService());
完整的Package类示例
把这些逻辑放到VSIX的Package类的Initialize方法里(这是VS服务初始化完成后的安全时机):
using System; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.ComponentModelHost; using DevExpress.Cocktail; using EnvDTE80; using Microsoft.VisualStudio.OLE.Interop; namespace YourVsixProject { [PackageRegistration(UseManagedResourcesOnly = true)] [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] [Guid(PackageGuidString)] public sealed class YourVsixPackage : Package { public const string PackageGuidString = "your-guid-here"; protected override void Initialize() { base.Initialize(); // 获取VS的DTE和ServiceProvider var dte2 = (DTE2)Package.GetGlobalService(typeof(SDTE)); var sp = new ServiceProvider(dte2 as IServiceProvider); // 获取VS的MEF容器 var componentModel = (IComponentModel)sp.GetService(typeof(SComponentModel)); var vsCompositionContainer = componentModel.DefaultCompositionContainer; // 集成到Cocktail(这里用方式二,直接复用VS容器) var cocktailHost = new CompositionHost(vsCompositionContainer); // 注册自定义部件 cocktailHost.ComposeParts(this); } } }
注意事项
- 确保项目引用了
Microsoft.VisualStudio.ComponentModelHost程序集(用来获取IComponentModel)。 - 你的MEF导出类要正确标记
[Export]属性,比如导出接口要写[Export(typeof(IMyService))]。 - 如果需要VS主动识别你的导出,还可以配合VS的
[ProvideExportedService]等属性一起使用。
内容的提问来源于stack exchange,提问作者MrTouya
相关产品推荐
相关产品推荐

