WCF has a concept called Known Types, which lets WCF handle subclasses and interface implementations passed to services. Normally you can just whack a KnownTypeAttribute on your DataContract and you’re good to go:
[DataContract]
[KnownType(typeof(Manager))]
public class Employee { ... }
In the example above, the service will be able to use the Manager subclass anywhere it expects an Employee.
This doesn’t help much when you want to use non-DataContract types like IPrincipal. Trying to pass a GenericPrincipal to a service operation that expects an IPrincipal gives you an error message like this (line breaks added for slightly improved legibility):
System.Runtime.Serialization.SerializationException: Type 'System.Security.Principal.GenericPrincipal' with data contract name 'GenericPrincipal:http://schemas.datacontract.org/2004/07/System.Security.Principal' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
One solution is to decorate your service contract with a ServiceKnownTypeAttribute:
[ServiceContract]
[ServiceKnownType(typeof(GenericIdentity))]
[ServiceKnownType(typeof(GenericPrincipal))]
public interface ISomeService {
[OperationContract]
String DoSomethingWith(IPrincipal principal);
}
While I don’t necessarily recommend exposing IPrincipal through your service, the technique is worth knowing about. Most of the search results I got mentioned KnownTypeAttribute and not ServiceKnownTypeAttribute.
Thanks to Steven Cheng who answered this question in his response to this post. Steven also provided a link to Bennie Haelen’s fantastic post on Handling Data Contract Object Hierarchies in WCF, which covers more than you could ever want to know about this stuff :-).