无需依赖SDK即可与Visual Studio进行交互



我有一些Workflow Foundation 4 ActivityDesigners,我想与Visual Studio IDE进行交互(他们是WF4的事实与问题无关)。

这些设计器在程序集中定义,我们称之为herpaderp.dll。最终,这个dll将被交付到服务器,在那里它的activity和其他代码将永远快乐地存在。

但是,在此之前,我希望我的设计人员能够检查当前的解决方案,以便为使用herpaderp.dll中定义的活动的人提供更好的设计时体验。类似于"让我们使用存储在解决方案中的示例数据测试此Activity配置;这是我在一个方便的组合框中找到的样本数据——请选择一个。

现在,这很简单。下面是原始实现:

var dteo = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(DTE));
var dte = dteo as DTE;
if(dte == null) return; // not in Visual Studio or other wierdness, bail
var samples = dte.GetSampleDatum(); // super awesome extension method

嘿,太棒了!但是有个小问题……herpaderp.dll现在必须引用以下程序集:

  • Microsoft.VisualStudio.Shell.10.0.dll
  • envdte.dll

这些程序集是SDK的一部分。对我来说,将它们打包并传送到服务器完全没有意义。这就像在我的大肠上又加了一个阑尾。

我如何打破这些依赖关系,同时保留与Visual Studio交互的能力,从我的设计器?

在我看来,我有三个可能的答案,没有一个是我特别高兴的。

  1. 在运行时使用IoC绑定到将为我执行交互的程序集。程序集可以引用SDK程序集,同时隐藏在herpaderp中定义的简单接口后面。不幸的是,这增加了一个不同的依赖,它只在设计时起作用,在服务器上是无用的。
  2. 在运行时使用它们的程序集限定名加载依赖项,并隐藏在dynamic后面。这违背了我的类型安全育种。另外,我不确定我是否能100%逃脱。
  3. 在运行时通过某种服务位置与Visual Studio包交互。我的解决方案提供了一个Visual Studio扩展,所以我不必担心编写它或强迫人们使用它。但是为了与它交互,我必须使用某种蹩脚的服务定位器废话模式,我非常鄙视它。服务定位器。Feh。此外,它还需要某种跨进程(或至少在同一进程中跨appdomain)的通信。

我相信选项3是我最好的选择。还有别的解决办法我没注意到吗?我讨厌我的三个答案中的一个是不是错了?

我的选择是使用WCF创建一个进程范围(通过命名约定)的命名管道来来回通信。

这工作得很好。我可以在Activity程序集中的内部定义服务和客户端,并在Package端实现服务。唯一需要注意的是,默认情况下,服务实现将在UI线程上处理调用,因此当从设计界面/客户端进行调用时,我不能阻塞UI线程。使用一些明智的扩展方法,我可以毫不费力地将客户端调用卸载到ThreadPool上,通过当前的SynchronizationContext将结果和异常编组回来。

我能够实现这个没有太多的努力。不幸的是,我最近意识到真正的问题是,我应该做的是在不同的程序集中交付我的设计器,这只能通过设计器安装程序交付。然后,活动将被交付到生产服务器,从而消除任何依赖问题。这需要一些我不知道的惯例和流程的内部知识。这篇MSDN博客详细介绍了我希望在问这个问题之前就知道的事情。

最新更新