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

3

7

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?

Smiley answered 13/3, 2010 at 11:21 Comment(1)
As for 1st question - both sides of coursePluck
N
2

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)

Neary answered 25/9, 2017 at 8:56 Comment(0)
R
1

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.

Resistive answered 13/3, 2010 at 11:55 Comment(1)
Does Silverlight 4 not have access to the same DataContractResolver?Smiley
R
0

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...

Reverberatory answered 18/7, 2011 at 20:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.