WCF makes heavy use of reflection. In order to support object inheritance one needs to help WCF by decorating DataContract with [KnownType(typeof(aType))] so the service reference will include the proper information. Below is a quick example:
The below data contract for an Animal also includes the known types of Cat and Dog:
[DataContract] [KnownType(typeof(Cat))] [KnownType(typeof(Dog))] public class Animal { [DataMember] public string Name { get; set; } } [DataContract] public class Dog : Animal { } [DataContract] public class Cat : Animal { }
Here, the service contract is working only with Animal:
[ServiceContract] public interface IServiceInterface { [OperationContract] string GetAnimalName(Animal anAnimal); }
And the implementation is looking for specific descendant classes (Cat & Dog):
public class ServiceInstance : IServiceInterface { public string GetAnimalName(Animal anAnimal) { if (anAnimal is Dog) return "Dog"; if (anAnimal is Cat) return "Cat"; return "Unknown"; }
}
The calling code could look something like this:
ServiceReferenceTest.ServiceInterfaceClient aClient = new ServiceReferenceTest.ServiceInterfaceClient(); var aCat = new ServiceReferenceTest.Cat(); Console.WriteLine(aClient.GetAnimalName(aCat));
Bottom line: WCF is an amazingly powerful way to build OOP web services.
If one comments out [KnownType(typeof(Cat))] and runs the program, the client will give the below runtime error:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:anAnimal. The InnerException message was ‘Error in line 1 position 261. Element ‘http://tempuri.org/:anAnimal’ contains data from a type that maps to the name ‘http://schemas.datacontract.org/2004/07/WcfServiceWEOTest:Cat’. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to ‘Cat’ to the list of known types – for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.’. Please see InnerException for more details.