0

我有一些希望与 Visual Studio IDE 交互的 Workflow Foundation 4 ActivityDesigners(它们是 WF4 的事实与问题无关)。

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

但是,在此之前,我希望我的设计人员能够检查当前的解决方案,以便为使用 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 扩展,因此我不必担心编写它或强迫人们使用它。但为了与之互动,我不得不使用某种蹩脚的 Service Locator BS 模式废话,我满怀激情地鄙视它。服务定位器。费。此外,它还需要某种跨进程(或至少在同一进程中跨 AppDomain)通信。

选项 3 是我最好的选择,我相信。我还缺少另一个解决方案吗?我讨厌我的三个答案之一是错的吗?

4

1 回答 1

0

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

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

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

于 2011-05-18T18:01:23.307 回答