Patterns for Compensating Lack of Inheritance in SOA

Solution 1:

No matter whether or not you think about SOA as implemented by SOAP, REST or messaging, services are document-centric. Services are not object-oriented.

While polymorphism is a strong design tool in OOD, it's not applicable in SOA because SOA modeling doesn't involve classes.

Solution 2:

I find Inheritance and concept of base class as the strongest point of OOP.

Don't overestimate power of inheritance - almost all GoF patterns are about avoiding wrong usage of inheritance.

But this is not encouraged in SOA.

No it is generally not encouraged. Why? Because in SOA you have a service providing some operations. The service itself is defined by service description (contract / interface). In case of SOAP services contract is described in WSDL. If you need to have another service providing same set of operations with little bit different behavior you you will just implement interface again and target client to a new service (by providing new endpoint URL). So inheritance with service contract "works" but it doesn't work in the same way with data contracts.

Each service operation usually accepts some data and return some data. These data are again described in service description. In case of SOAP services data are described as XSD. When you send data from client to service (or in reverse direction) data must be serialized and destination must be able to deserialize them (unless you want to work with SOAP envelopes directly or unless you want to use xsd:any = untyped XML as passed data). If you want to use inheritance in data contract you must somehow include information about derived contracts into the service description. Only after including this information into service description you can inform service consumers about existence of inherited data contracts (they need this information to work with derived types).

WCF offers ability to work with inherited data contracts. You can use KnownTypeAttribute, ServiceKnownTypeAttribute attribute or DataContractResolver. You can also check this great article for more details.

In case of non interoperable and tightly coupled systems (non SOA) you can also use NetDataContractSerializer which allows you to use inheritance without any limitations because each serialized message contains information about CLR type needed for deserialzation and clients with service should share data contract assemblies.