【问题标题】:Can WCF service transmit type (client doesn't know this type) information?WCF 服务可以传输类型(客户端不知道这种类型)信息吗?
【发布时间】:2010-12-04 03:32:59
【问题描述】:

我正在开发一个简单的插件框架。 WCF 客户端需要创建一个“ISubject”实例,然后发送回服务端。 'ISubject' 可以由用户扩展。客户端在运行时唯一知道的是“ISubject”子类的 ID。

首先,客户端需要获取“ISubject”的特定子类的类型信息。其次,客户端使用反射枚举所有成员以创建自定义属性编辑器,以便可以为每个成员分配适当的值。最后,客户端创建该子类的实例并发送回服务。

问题是客户端如何通过WCF通信获取类型信息?

我不希望客户端加载存在子类('ISubject')的程序集。

谢谢

【问题讨论】:

  • 这听起来不太乐观。你真正想解决什么问题?
  • 不,你不能这样做 - WCF 是关于 序列化 (XML) 消息 - 你不能通过网络发送未知对象类型并重新组装它们客户端不知道它们... WCF 不是“对象远程处理”类型的系统(如 DCOM 或 CORBA)- 设计
  • Spender,我定义了一个接口ISubject,它可以被插件框架用户扩展。框架(在服务器端运行)可以在运行时从第三方程序集加载 ISubject 的子类。客户端需要创建一个扩展子类的实例并发送回服务器端。我使用 WCF 进行服务器和客户端之间的通信。所以,问题是客户端如何获取类型信息来创建子类的实例(我使用反射,所以需要类型信息)。注意:我不想客户端加载第三方程序集。

标签: wcf service


【解决方案1】:

首先,您需要知道,在您描述的场景中,WCF 不会向您的客户端提供任何类型信息的神奇方式。如果你要这样做,你必须自己提供一个机制。

接下来,要了解 WCF 并不真正将对象从服务器传递到客户端,反之亦然。它传递的只是 XML 信息集。通常,传递的 XML 信息集包括发送方存在的某个对象的序列化表示;在这种情况下,如果客户端知道该类型(即可以从其程序集中加载类型的元数据),它可以反序列化 XML 以在客户端实例化相同的对象。如果客户端没有类型元数据,则不能:这是 WCF 的正常情况,除非数据协定类型位于服务器和客户端实现共享的程序集中(通常不是一个好主意)。

通常使用 WCF 的方式(例如,如果客户端使用 Visual Studio 中的“服务引用”实现),发生的情况是服务发布描述其操作的 WSDL 元数据和操作参数的 XML 架构并返回值,并从中生成一组类型以用于客户端实现。这些 .NET 类型与服务实现使用的数据协定类型不同,但它们是“等价的”,因为它们可以序列化为通过网络传递的相同 XML 数据。通常这种类型生成是在 Visual Studio 的设计时完成的。

为了做你想做的事情,本质上是在运行时生成这种类型,你需要一些机制,通过这种机制,客户端可以充分了解表示各种类型对象的 XML 的结构实现 ISubject 以便它可以理解从服务接收的 XML 并生成服务期望返回的适当 XML(直接使用 XML,或以某种方式反序列化/序列化它)。如果您真的非常想这样做,可能的方法可能是:

  • 一些带外机制,客户端预先配置了与它可能看到的每个 ISubject 子类相对应的相关类型信息。盲人回答中提供的链接是一种方法。

  • 提供单独的服务操作,通过该操作,客户端可以将子类的 ID 转换为子类的类型元数据(可能作为 XSD 模式,客户端可以从中生成合适的可序列化 .NET 类型来往返XML)。

  • 原则上,服务在包含序列化对象的响应的标头中以某种格式传递类型元数据也是可行的。客户需要以适当的方式阅读、解释和处理类型信息。

无论哪种方式,都需要付出很多努力,而且不是使用 WCF 的标准方式。你将不得不决定它是否值得。

【讨论】:

  • 你好克里斯,非常感谢你的回答。我喜欢你上面提到的第三种方式。感谢您的详细解释。
【解决方案2】:

我认为你可能遗漏了一些东西 :)

Web 服务和 WCF 的一个主要概念是我们可以通过网络传递我们的对象,并且客户端可以使用与服务器相同的对象。此外,当客户端在 Visual Studio 中添加服务引用时,服务器将向客户端发送它需要了解的有关将通过网络传递的任何类型的所有详细信息。

应该不需要反思。

要介绍的内容很多,但我建议您从涵盖 WCF 数据合同的本教程开始 - http://www.codeproject.com/KB/WCF/WCFHostingAndConsuming.aspx

【讨论】:

  • 谢谢格雷格。但在我的情况下,客户端不知道要传输的对象类型。 WCF 服务只知道基本接口 - ISubject,具体类型由框架用户定义。
  • 抱歉,这没有意义。客户端如何接收它不知道的对象?当您添加服务引用时,您的客户端应该会“意识到”这些对象,或者(如果服务引用未提供元数据交换信息)您应该能够根据接收到的数据创建代理客户端对象。您说 WCF 服务只知道基本接口,并且客户端不知道对象的类型 - 这是不可能的情况。
【解决方案3】:

要反序列化一个对象,接收方需要拥有定义类型的程序集。

也许您应该考虑某种类型的远程处理或代理设置,其中 ISubject 的实例位于一侧,而另一侧调用它。如果您需要通过网络编组大量数据,这可能会出现问题。

【讨论】:

  • 我对 WCF 完全陌生。能否说的更具体一点?
  • 我对 WCF 也没有很多经验,但一般的问题是“我有一种可以在一台机器或进程上实例化的类型,我需要在另一台机器或进程上使用它” .要搜索的关键字是 Remoting、MarshalByRefObject 和 Remote Procedure Calls。
  • -1 第一句话对于 WCF 是不正确的。远程处理无关紧要,只会混淆 OP。 MarshalByRefObject 远远超出了范围,RPC 也是如此:)
【解决方案4】:

wcf 需要知道应该通过网络发送的真实对象(不是接口!)。因此,您必须使 WCF 服务的服务器和客户端代理端满足他们知道类型的要求。如果您在创建 WCF 服务时不知道对象类型,则必须找到一种以动态方式执行此操作的方法。我使用来自here 的解决方案将 knownTypes 获取到我的 WCF 服务。

[ServiceContract(SessionMode = SessionMode.Required]
[ServiceKnownType("GetServiceKnownTypes", typeof(KnownTypeHelper))]//<--!!!
public interface IWCFService
{
    [OperationContract(IsOneWay = false)]
    object DoSomething(object obj);
}

如果您有类似上述代码的“通用”内容,您必须确保无论您在运行时的对象是什么,您的 WCF 服务都必须知道该对象。

您为您的客户端编写了一个子类并将其发送回服务。如果你想这样做,WCF(clientproxy and server!) 需要知道你的子类的真实类型。

【讨论】:

  • 您好,blindmeis,在我的例子中,具体类型(从 ISubject 继承)是在插件包中定义的,并且在设计时不能是“已知类型”。谢谢你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多