【发布时间】:2010-11-29 22:49:35
【问题描述】:
我们希望在同一台机器上运行的两个 .NET 应用能够相互通信。我们想要三个项目。包含接口的库。实现接口的“服务器”应用程序和使用接口与服务器通信的“客户端”应用程序。我们不希望客户端引用服务器。
我们有一个测试应用程序可以通过远程处理执行此操作,但最近发现远程处理正在被 WCF 取代。由于这是新的开发,我们认为我们应该使用 WCF,但我们还没有设法使其与 WCF 一起工作,并且想知道这是否可能?
编辑:
抱歉,我在上面没有详细说明,但当时我无法访问任何代码。我正在和另外两个人一起做这个项目,还没有仔细研究过他们的 IPC 资料。我知道他们目前认为 WCF 不能做他们希望它做的事情,我希望能够向他们证明它可以。
我已经开始查看我的同事在这方面的尝试,并将继续根据我的理解更新这篇文章。
下面是他们的远程测试代码的简化版本。他们希望能够使用 WCF 来做到这一点,但到目前为止还无法让它发挥作用。
- 库\IMessage.cs
- 库\IService.cs
- ServiceApp\Service.cs
- ServiceApp\ServiceMessage.cs
- ServiceApp\ServiceProgram.cs
- 客户端应用\ClientProgram.cs
ServiceApp 和 ClientApp 程序集都引用了 Lib 程序集。它们不相互引用。
当我能够更好地解释他们在 WCF 中复制此行为的尝试时,我将再次编辑此内容。在这一点上,我真正知道的是他们正在使用 NetNamedPipeBinding 并且在客户端应用程序抱怨它无法访问服务程序集时遇到问题。
编辑:
以下是 WCF 测试代码的简化版本。
- 库\IMessage.cs
- 库\IService.cs
- ServiceApp\Service.cs
- ServiceApp\ServiceMessage.cs
- ServiceApp\ServiceProgram.cs
- 客户端应用\ClientProgram.cs
ClientProgram 中的以下行引发异常:
IMessage msg2 = service.CreateMessage("Hello World");
这是一个例外:
无法加载文件或程序集“ServiceApp,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件。
编辑:
为了了解 Steven 的最新评论,我在 IMetadataExchange 上进行了谷歌搜索,当然它的第一次点击是 MSDN Page。这个页面说:
无需在您的服务实现中实现 MetadataReference 合同。而是将 ServiceMetadataBehavior 添加到服务描述中。
或者,在使用配置时,将端点元素的合同属性设置为 IMetadataExchange。有关示例,请参阅如何:使用配置文件为服务发布元数据。
有关在 WCF 中发布元数据的详细信息,请参阅Publishing Metadata。
因为,对于本示例,我没有使用配置文件,而是选择转到 Publishing Metadata 链接。从那里我转到How to: Publish Metadata for a Service Using Code 链接,它有一个很好的例子,我用来修改我的service app code。添加的代码在第 15-20 行。
经过一些工作,我能够添加服务参考。该服务必须正在运行,但如果您通过 Visual Studio 运行该服务,则您没有添加服务引用的选项。另外,我仍然不明白“在解决方案中发现服务”选项应该如何工作。最后,我能够通过 bin/debug 文件夹打开手动运行服务,然后输入我添加到我的服务应用程序的 URL 来添加引用。如果这是正确的方式,那就太尴尬了。
毕竟code generated 对我没有任何帮助。首先,它重新创建了我的 IService 接口,但将我所有的 IMessage 转换为对象并稍微不同地装饰它。如果使用它们的接口,那么它不仅会使用不同的 IService,那么我的服务实际上会实现,而且这个 IService 中的方法甚至没有相同的签名!
除此之外,我认为我必须更改我的客户端以使用新生成的对象中的对象,所以我更改了我的 client code。
现在,当我尝试运行它时,我在第 4 行收到以下错误:
格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数 http://tempuri.org/:msg 时出错。 InnerException 消息是“XML 元素”“http://tempuri.org/:msg”不包含预期的属性“http://schemas.microsoft.com/2003/10/Serialization/:Type”。反序列化器不知道要反序列化哪种类型。检查被序列化的类型是否与被反序列化的类型具有相同的合同。有关详细信息,请参阅 InnerException。
编辑:
自从我添加赏金以来,悬赏还剩一天,但没有任何答案。在赏金时间结束之前我有什么可以澄清的吗?
编辑:
最后我们选择了远程处理,因为 WCF 似乎无法实现我们想要做的事情。 Steven Sudit 因他的所有帮助而获得了赏金,尽管这一切都发生在我提供赏金之前。
【问题讨论】:
-
您为什么不想让客户端应用程序引用服务器?还是您只是说您不希望客户端加载服务器的程序集?
-
我们不希望客户端加载服务器的程序集
-
嗯,这是有道理的,但在 WCF 中绝对可以避免。一种方法是在一个程序集中定义接口,两者都使用。另一种是使用Service References中的代码生成机制。
-
接口在共享程序集中定义。
-
如果您的服务和客户端将始终保持在一起,请考虑使用 MEF。它可以为您提供您正在寻找的解耦架构,而无需 Remoting 或 WPF 的开销。 codeplex.com/MEF