Using custom DataContractResolver in WCF to migrate inheritance trees using generics

I have a WCF service in which there are operations that accept a non-generic template as a parameter.

[DataContract] class Foo { ... } 

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

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

To make this work, I used to have to register KnownTypes for the Foo class and include all possible Bar options (e.g. Bar<string> , Bar<int> and even Bar<List<string>> ).

However, with DataContractResolver in .NET 4, I should be able to create a resolver that correctly stores (and restores) classes.

My questions:

  • Are DataContractResolvers typically used only by the service, not the client? If so, how would this be useful in this scenario?

  • Am I mistaken to write a DataContractResolver that serializes the fully qualified type name of a typical type, for example Bar`1[List`1[string, mscorlib], mscorlib] ? Could the same DataContractResolver on the client side restore these types?

+7
c # wcf datacontract
source share
3 answers

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

+1
source share

I don’t know what a typical use case is for a DataContractResolver, but according to this article ( MSDN in a DataContractResolver ) this should be easily accomplished using "SharedTypeResolver" and sharing the Assemblies containing the contract.

Warning: Therefore, although this seems possible, I’m not quite sure that it is a good idea from a design point of view, as this will weaken the expressiveness of the contract. These types tunnel the contract and break compatibility with other programming languages, and this can lead to the fact that using an open standard such as SOAP is the right solution in the first place. DataContract exists for non- generic assemblies ...

0
source share

I used DataContractResolver before; and these are my conclusions:

  • Both client and server require permission; as serialization and deserialization occur at both ends. Obviously, the same Resolver is used.
  • Type names are a standard piece of information that the DataContractSerializer produces. However, this is a name of type NAME, and not the full (assembly) qualified name

Basically, a custom resolver allows you to add it to the WCF client and server as a β€œ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 caches them based on some attribute. I can provide you with sample code if you want - it's all pretty simple.

KnownTypeAttribute (for example, using the provided method to return all known types) can also be used; but a custom resolver allows a more flexible approach, such as dynamically loading types (for example, a plug-in system) and performing its own mapping (Type => type name and vice versa)

0
source share

All Articles