【问题标题】:Remoting or WCF for new development (between two .NET apps on the same machine) using interfaces?使用接口进行新开发(在同一台机器上的两个 .NET 应用程序之间)的远程处理或 WCF?
【发布时间】:2010-11-29 22:49:35
【问题描述】:

我们希望在同一台机器上运行的两个 .NET 应用能够相互通信。我们想要三个项目。包含接口的库。实现接口的“服务器”应用程序和使用接口与服务器通信的“客户端”应用程序。我们不希望客户端引用服务器。
我们有一个测试应用程序可以通过远程处理执行此操作,但最近发现远程处理正在被 WCF 取代。由于这是新的开发,我们认为我们应该使用 WCF,但我们还没有设法使其与 WCF 一起工作,并且想知道这是否可能?


编辑:

抱歉,我在上面没有详细说明,但当时我无法访问任何代码。我正在和另外两个人一起做这个项目,还没有仔细研究过他们的 IPC 资料。我知道他们目前认为 WCF 不能做他们希望它做的事情,我希望能够向他们证明它可以。

我已经开始查看我的同事在这方面的尝试,并将继续根据我的理解更新这篇文章。

下面是他们的远程测试代码的简化版本。他们希望能够使用 WCF 来做到这一点,但到目前为止还无法让它发挥作用。

ServiceApp 和 ClientApp 程序集都引用了 Lib 程序集。它们不相互引用。

当我能够更好地解释他们在 WCF 中复制此行为的尝试时,我将再次编辑此内容。在这一点上,我真正知道的是他们正在使用 NetNamedPipeBinding 并且在客户端应用程序抱怨它无法访问服务程序集时遇到问题。


编辑:

以下是 WCF 测试代码的简化版本。

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

标签: c# .net wcf remoting


【解决方案1】:

这是使用 WCF 执行类似远程处理的一种模式:

  • 3 个项目:服务器、客户端、shared.dll
  • 服务器和客户端都引用shared.dll
  • 将带有[ServiceContract]的服务接口放入shared.dll中
  • 将服务实现类放入服务器
  • 不要为您的数据类型使用接口
  • 创建仅包含您希望在客户端和服务器之间共享的逻辑(例如验证)的基本 DataContract 类型
  • 将您的 DataContract 数据类型放入 shared.dll 中
  • 不要使用 NetDataContractSerializer(就像您在代码中所做的那样)

当然,这个主题有很多变化。例如。您可以使用#if 在服务器和客户端项目之间共享代码文件,而不是共享 dll,以进行不同的编译。

【讨论】:

  • 让它在没有接口的情况下工作很简单,但我们最接近的让它与接口一起工作(这是他们的要求)是使用 NetDataContractSerializer。
【解决方案2】:

我刚刚将一个程序从远程处理切换到 WCF,我遇到了很多过去可以在远程处理中无缝工作但在 wcf 中导致问题的东西:

  • CallContext 类已消失。我用它来传递一些关于例如的信息。当前选择的语言和有关用户的一些信息。使用 WCF,我必须创建一个 MessageInspector 来为每个请求添加带有此信息的标头。
  • 异常不再原封不动地通过。相反,您需要使用 FaultException 和 FaultContracts。
  • 代理似乎没有那么轻。我需要处理它们,而不是让它们被垃圾收集,否则我的服务将挂起。 (实际上,它甚至不像调用 Dispose 来正确终止代理那么简单,您需要一个相当复杂的 try、catch、finally 序列来针对不同类型的异常调用 Close 和 Abort。)关闭代理的需要会导致一些问题我希望我的 IoC 框架管理代理的问题。

我并不是说你应该使用 Remoting,我只是说有理由考虑 Remoting。它绝对是更简单的设置和开始工作。

我猜你可能会争辩说,我遇到这些问题只是因为我没有在我的远程处理程序中使用最佳实践。 :-P

【讨论】:

  • WCF 肯定更复杂。
【解决方案3】:

WCF 是要走的路,具体检查一下 Net Named Pipe 与 WCF 的绑定。这将允许在同一台机器上进行非常快速的进程间通信。

如果您的生产部署以 Windows Server 2008 为目标,那么您可以利用 IIS 7 作为托管环境。查看Extend Your WCF Services Beyond HTTP With WAS

那里有很多 WCF 入门类型信息。签出:

如果您在开始时遇到问题,请发布任何具体错误或示例,您可能已经演示过了,我相信这里有人可以提供帮助!

【讨论】:

  • 网络命名管道绑定与 IPC 的 TCP/IP 相比如何?如果我没记错的话,TCP/IP 在连接到 localhost 时会使用共享内存。
  • @StevenSudit 不确定 net.tcp 如何与 net.pipe 相提并论,我自己没有进行任何正式测试。我想它们可能具有可比性,但如果没有明确的知识/经验,我会倾向于 net.pipe。如果有人在那里有经验,我肯定会感兴趣,尽管我可能会坚持使用 net.pipe,因为隐含的意图(对我来说)更清楚。我们确实在 remoting 和 net.pipe 之间做了一些非正式的测试,测试结果在这里:stackoverflow.com/questions/1295353/…
  • @Zach:命名管道在不在同一台机器上使用时会出现一些性能问题,而 TCP/IP 似乎在这两种情况下都能正常工作。
  • 从我最近的阅读中,我认为微软选择禁止在 WCF 中使用命名管道,而不是在同一台机器上使用它们。
  • 绝对是 WCF。如果您将架构更改为在 Intranet 上使用多个盒子,则使用本地 NetNamedPipes 和 NetTcp。
【解决方案4】:

Remoting 有一些用例,例如单个进程内的应用程序域之间的通信。话虽如此,是的,WCF 是要走的路。不过,从你所说的一些事情来看,我不确定你是否理解这应该如何工作。

在 WCF 中做事的常用方法是创建一个完全由数据传输对象(所有属性,无代码)和接口组成的共享程序集。双方都引用这个程序集,但客户端使用服务器的服务引用。这有帮助吗?

【讨论】:

  • WCF 也可以桥接 AppDomain。请参阅 Juval Lowy 网站 idesign.net 下载部分中的 In-Proc Hosting 示例。
  • 我会在收到带有链接的电子邮件后立即查看。
  • WCF 可以做很多事情,但考虑一下您将程序集加载到 AppDomain 中只是为了隔离的情况,其中没有 WCF 支持。
  • @Matt 我终于得到了下载链接并查看了示例。但是,里面没有我没见过的东西。
  • @Steven 我刚刚意识到,在我进行编辑后,我从未回复您的实际答案。我们确实有一个包含接口但没有对象的共享程序集。我无法添加服务参考。 Visual Studio 坚持认为解决方案中没有服务。
【解决方案5】:

两者都用过。

一定要使用 WCF。

Remoting 的文档记录很差,而且很敏感。相比之下,WCF 要容易得多。不确定您遇到的问题,但有大量关于 WCF 的文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-09
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    相关资源
    最近更新 更多