我正在研究一个简单的插件框架。 WCF客户端需要创建“ISubject”的实例,然后发送回服务端。 “ISubject”可以由用户扩展。客户端在运行时唯一知道的是'ISubject'的子类的ID。
首先,客户端需要获取“ISubject”的特定子类的类型信息。其次,客户端使用反射来枚举所有成员以创建自定义属性编辑器,以便每个成员都可以使用适当的值进行赋值。最后,客户端创建该子类的实例并发送回服务。
问题是客户端如何通过WCF通信获取类型信息?
我不希望客户端加载子类('ISubject')存在的那个程序集。
由于
答案 0 :(得分:3)
首先,您需要知道,在您所描述的场景中,WCF没有任何神奇的方式可以向您的客户端提供任何类型信息。如果你打算这样做,你必须自己提供一种机制。
接下来,要了解WCF并未真正将对象从服务器传递到客户端,反之亦然。它传递的只是XML信息集。通常,传递的XML信息集包括发送方存在的某个对象的序列化表示;在这种情况下,如果客户端知道该类型(即可以从其程序集加载类型的元数据),它可以反序列化XML以在客户端实例化相同的对象。如果客户端没有类型元数据,则不能:这是WCF的正常情况,除非数据协定类型在服务器和客户端实现共享的程序集中(通常不是一个好主意)。
通常使用WCF的方式(例如,如果客户端是使用Visual Studio中的“服务引用”实现的),那么服务会发布描述其操作的WSDL元数据以及操作参数的XML模式并返回值,并从这些值生成一组类型以供在客户端实现中使用。这些类型与服务实现使用的数据协定类型不同,但它们是“等效的”,因为它们可以序列化为通过网络传递的相同XML数据。通常,此类型生成在Visual Studio中的设计时完成。
为了做你想做的事情,这本质上是在运行时进行这种类型生成,你需要一些机制,通过这种机制,客户端可以获得足够的XML结构知识,代表各种类型的对象实现ISubject以便它可以理解从服务接收的XML并生成服务期望的适当XML(直接使用XML,或以某种方式反序列化/序列化)。如果你真的,真的想这样做,可能的方法可能是:
一些带外机制,客户端预先配置了与其可能看到的ISubject的每个子类相对应的相关类型信息。在blindmeis的答案中提供的链接是一种方法。
提供单独的服务操作,通过该操作,客户端可以将子类的ID转换为类型的子类的元数据(可能作为XSD架构,客户端可以从中生成合适的可序列化.NET类型以进行往返) XML)。
原则上,服务在包含序列化对象的响应的头部内以某种格式传递类型元数据也是可行的。客户需要以适当的方式阅读,解释和处理类型信息。
无论哪种方式,都需要付出很多努力,而不是使用WCF的标准方式。你必须决定它是否值得。
答案 1 :(得分:1)
我想你可能会遗漏一些东西:)
Web服务和WCF的一个主要概念是我们可以通过网络传递对象,客户端可以使用与服务器相同的对象。此外,当客户端在Visual Studio中添加服务引用时,服务器将向客户端发送有关将通过网络传递的任何类型所需的所有详细信息。
不应该反思。
有很多要涵盖的内容,但我建议您从本教程开始,该教程涵盖WCF DataContracts - http://www.codeproject.com/KB/WCF/WCFHostingAndConsuming.aspx
答案 2 :(得分:0)
要反序列化对象,接收方需要具有定义类型的程序集。
也许您应该考虑某种类型的远程处理或代理设置,其中ISubject的实例位于一侧而另一侧则回调它。如果您需要通过网络整理大量数据,这可能会有问题。
答案 3 :(得分:0)
wcf需要知道应该通过网络发送的真实对象(不是接口!)。所以你必须从WCF服务满足服务器和clientproxy端,他们知道这些类型。如果您在创建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和server!)需要知道你的子类的真实类型。