在WCF中使用自定义DataContractResolver传输涉及泛型的继承树

7
我有一个WCF服务,在其中有一些操作接受非泛型基类作为参数。
[DataContract]
class Foo
{ ... }

这个基类被一些泛型类继承,例如

[DataContract]
class Bar<T> : Foo
{ ... }

为了使其正常工作,我之前必须为Foo类注册KnownTypes,并包括所有可能的Bar变体,例如Bar<string>Bar<int>甚至Bar<List<string>>
然而,在.NET 4中使用DataContractResolver,我应该能够构建一个正确存储(和恢复)类的解析器。
我的问题:
1. DataContractResolvers通常只在服务端使用,而不是客户端吗?如果是这样,在这种情况下它会有什么用处?
2. 我是否错误地编写了一个DataContractResolver,它序列化了泛型类型的完全限定类型名称,例如Bar`1[List`1[string, mscorlib], mscorlib]?同样的DataContractResolver在客户端上能否还原这些类型?

关于第一个问题 - 当然是双方。 - EvAlex
3个回答

2
我之前使用过,以下是我的发现:
  1. 客户端和服务器都需要该解析器,因为序列化和反序列化在两端都进行。显然,使用相同的解析器。
  2. 类型名称是DataContractSerializer生成的信息的标准部分。但是,它只是类型名称,而不是完全(程序集)限定名称。
基本上,自定义解析器允许您将其添加到WCF客户端和服务器作为行为:
`foreach (OperationDescription operation in myWCFService.Description.Endpoints[0].Contract.Operations)
    {
      operation.Behaviors.Find<DataContractSerializerOperationBehavior>()
          .DataContractResolver = new MyDataContractResolver();
    }`

对于客户端,您需要做同样的事情:

      `foreach (var operation in base.ChannelFactory.Endpoint.Contract.Operations)
  {
    operation.Behaviors.Find<DataContractSerializerOperationBehavior>()
        .DataContractResolver = new MyDataContractResolver();
  }`

我的解析器会从配置的位置动态加载类型,并根据某些属性进行缓存。如果您愿意,我可以提供一些示例代码-它们都非常基础。
也可以使用KnownTypeAttribute(例如使用提供的方法返回所有已知类型);但是自定义解析器允许更灵活的方法,例如动态加载类型(例如插件系统)并执行自己的映射(Type =>类型名称及其反之亦然)。

1

我认为这应该在两端都能工作,但我不确定这是否是一个好主意;它需要额外的配置,并且在Silverlight等上无法工作。但对于每一端使用相同的位元,它可能适用于“完整”的.NET。


1
Silverlight 4没有访问相同的DataContractResolver吗? - Benson

0

不知道DataContractResolver的典型用例是什么,但根据这篇文章(MSDN on DataContractResolver),使用“SharedTypeResolver”和包含合同的程序集共享应该很容易实现。

需要注意的一点是: 虽然这似乎是可能的,但我不确定从设计角度来看这是否是一个好主意,因为这将削弱合同的表达能力。这些类型会隧道合同并破坏与其他编程语言的兼容性,这将导致问题,即首先使用像SOAP这样的开放标准是否是正确的解决方案。DataContract不是用于共享程序集的...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接