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

时间:2010-03-13 11:21:22

标签: c# .net wcf datacontract

我有一个WCF服务,其中有一些操作接受非泛型基类作为参数。

[DataContract]
class Foo
{ ... }

这个基类依次由

这样的泛型类继承
[DataContract]
class Bar<T> : Foo
{ ... }

为了使这个工作起作用,我之前必须为Foo类注册KnownTypes,并且包括Bar的所有可能变体(例如Bar<string>Bar<int>甚至{{1 }})。

但是,使用.NET 4中的DataContractResolver,我应该能够构建一个正确存储(和恢复)类的解析器。

我的问题:

  1. DataContractResolvers通常只在服务端使用,而不是在客户端使用?如果是这样,在这种情况下如何有用呢?

  2. 编写一个DataContractResolver是错误的,它会序列化泛型类型的完全限定类型名称,例如Bar<List<string>>?客户端上的DataContractResolver不能恢复这些类型吗?

3 个答案:

答案 0 :(得分:1)

我希望能在两端工作,但我不确定这是一个好主意;它需要额外的配置,并且无法在Silverlight等上运行。但它可能适用于“完整”的.NET,每端都有相同的位。

答案 1 :(得分:1)

我之前使用过DataContractResolver;这些是我的发现:

  1. 客户端和服务器都需要解析器;因为序列化和反序列化发生在两端。显然,使用相同的解析器。
  2. 类型名称是DataContractSerializer生成的信息的标准部分。但是,它只是NAME类型,而不是完全(程序集)限定名称
  3. 基本上,自定义解析器允许您将其作为行为添加到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 =&gt;类型名称,反之亦然)

答案 2 :(得分:0)

不知道DataContractResolver的典型用例是什么,但根据本文(MSDN on DataContractResolver),这应该可以通过“SharedTypeResolver”和共享包含合同的程序集轻松完成。

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