开发者

Using custom DataContractResolver in WCF, to transport inheritance trees involving generics

开发者 https://www.devze.com 2022-12-22 16:31 出处:网络
I\'ve got a WCF service, in which there are operations which accept a non-generic base class as parameter.

I've got a WCF service, in which there are operations which accept a non-generic base class as parameter.

[DataContract]
class Foo
{ ... }

This base class is in turn inherited, by such generics classes as

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

To get this to work, I'd previously have to register KnownTypes for the Foo class, and have these include all possible variations of Bar (such as Bar<string开发者_开发问答>, Bar<int> and even Bar<List<string>>).

With the DataContractResolver in .NET 4, however, I should be able to build a resolver which properly stores (and restores) the classes.

My questions:

  1. Are DataContractResolvers typically only used on the service side, and not by the client? If so, how would that be useful in this scenario?

  2. Am I wrong to write a DataContractResolver which serializes the fully qualified type name of a generic type, such as Bar`1[List`1[string, mscorlib], mscorlib] ? Couldn't the same DataContractResolver on the client side restore these types?


I have used a DataContractResolver before; and these are my findings:

  1. Both client AND server require the resolver; as serialization and deserialization takes place at both ends. Obviously, the same Resolver is used.
  2. The type names are a standard part of the information the DataContractSerializer produces. However, it is just the type NAME, not a fully (assembly) qualified name

Basically, a custom resolver allows you to add it to your WCF client and server as Behavior:

`foreach (OperationDescription operation in myWCFService.Description.Endpoints[0].Contract.Operations)
    {
      operation.Behaviors.Find<DataContractSerializerOperationBehavior>()
          .DataContractResolver = new MyDataContractResolver();
    }`

For the client, you do the same:

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

My resolver dynamically loads types from a configured location and based on some attribute, caches them. I can provide you some sample code if you like - it's all pretty basic.

KnownTypeAttribute (e.g. using a provided method to return all known types) is also usable; but the custom resolver allows a more flexible approach, such as dynamically loading types (e.g. a plugin system) and doing your own mapping (Type => type name and vice versa)


I would expect that to work at both ends, but I'm not sure it is a great idea; it requires extra configuration, and won't work on Silverlight etc. But it'll probably work for "full" .NET with the same bits at each end.


Don´t know what the typical use-case for the DataContractResolver is, but according to this article (MSDN on DataContractResolver) this should be easily accomplished with the "SharedTypeResolver" and sharing of the Assemblies that contain the contract.

A word of caution: So while this seems to be possible I´m not quite sure if this is a good idea from a design point of view, as this will weaken the expressivness of the contract. Those types would tunnel the contract and ruin compatibility with other programming languages, and this would lead to the question if using an open standard like SOAP is the right solution in the first place. DataContract is there for not sharing assemblies...

0

精彩评论

暂无评论...
验证码 换一张
取 消