Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Serialization with object inheritance?

I have two objects, one is in our enterprise level and another in in our service level. The service object is inheriting from the enterprise. Here is a quick example:

[DataContract]
public class EnterpriseObject{
     [DataMember]
     int ID{get; set;}

     string InternalUse{get; set;}
}

[DataContract]
public class ServiceObject: EnterpriseBaseObject{
     [DataMember]     
     string Address{get; set;}
}

Is it possible to only expose the ServiceObject (with inherited properties from EnterpriseObject) in the serialization? I do not want the client to see the enterprise object listed as an option? As you can see in the example the DataMember attribute is not set for the InternalUser property. Is that the only way to do it? Thanks

like image 302
DDiVita Avatar asked Mar 18 '09 14:03

DDiVita


People also ask

How do you serialize an object in WCF?

This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class. DataContractSerializer dcs = new DataContractSerializer(typeof(Person)); // This can now be used to serialize/deserialize Person but not PurchaseOrder.

What is by serialization with respect to WCF?

The process forms a sequence of bytes into a logical object; this is called an encoding process. At runtime when WCF receives the logical message, it transforms them back into corresponding . Net objects. This process is called serialization.

Which namespace is used for serialization in WCF?

By default WCF uses the DataContractSerializer class to serialize data types.

What is used if you expect the service to accept and return inherited types?

If you expect the service to accept and return an inherited type then we use the knowntype attribute.


2 Answers

You handle inheritance by adding a [KnownType(typeof(ServiceObject))] to EnterpriseBaseObject - however, the EnterpriseBaseObject is still part of the contract, and its existance will be public. But only members marked [DataMember] will be published.

One option (to remove the inheritance) is to have a separate DTO for serialization purposes, and have a conversion between the DTO version and the actual version - but that makes extra work.

like image 123
Marc Gravell Avatar answered Oct 16 '22 13:10

Marc Gravell


Can you change this from an Is A pattern to a Has A pattern? If ServiceObject has an EnterpriseObject you could then expose just the properties you need.

Edit

If I understand correctly you want to expose ServiceObject to clients including all its properties (That are marked as a DataMember) including properties inherited from EnterpriseObject. But you don't want the client to know that there is an object called EnterpriseObject.

You can do this by hidding the fact that there is an enterprise object. Instead of using an "Is A" relationship which is an inheritance pattern. You can use a composition or "Has A" pattern.

public class ServiceObject
{
   private EnterpriseObject _myEntObject;

   public string MyServiceObjectProperty
   {
      get;
      set;
   }

   public string MyEntObjectProperty
   {
     get { return _myEntObject.MyEntObjectProperty;}
   }
}

Now you have isolated your EnterpriseObject from your client. All your communicating is that ServiceObject has some properties you are not exposing to your client that this is implemented on the server by some other object.

This is also simillar to having a DTO, which is an object that's sole purpose is to transmit data. DTO's allow you hide your implementation by giving your clients exactly what they need in the format they need, without exposing your internal objects.

like image 44
JoshBerke Avatar answered Oct 16 '22 13:10

JoshBerke