How do I use KnownType to enable polymorphic return values in a WCF service contract?
I am converting a remoting interface to WCF, however I have a method that is declared to return "object" and can return a number of different types (mostly different enums)
Where can I find an example of coping with this?
(I am using a shared contract assembly that contains all the types rather than generating a clie开发者_如何学Pythonnt proxy if that makes a difference.)
Well, the documentation contains an example of using the KnownTypeAttribute. Note that it allows multiple attributes on the same class, so you can identify more than one polymorphic child type.
This is quite limited functionality since it only allows you to specify types known at design-time, so it doesn't really fit into the extensibility and maintainability mindset that normally makes us use polymorphism in the first place.
AFAIR, this limitation exists mainly because of constraints in WSDL/XSD, to which WCF contracts are often translated. We must always recall that only messages travel across the wire - not objects. The client at the other end may not be a .NET application at all, so for the sake of interoperability, these are the constraints we have to accept.
I usually find that a more static redesign of the service interface is often a better solution. You could also consider exposing the return type as System.Object, which will translate to xs:any, but obviously you will lose type safety along the way.
WCF has an advanced option that allows you to share types between server and client, so this may also be a solution for you. However, you lose interoperability and a host of other goodness if you do this, so consider this option carefully before you choose it.
Take a look at this KnownTypeProvider We use this for silverlight connections and use a NetDataContractSerializer when we are sharing the same assemblies between the client and server.
I'm not sure KnowType attr will work with enums as they can't be inherited?
This is what I did in the end, however I am lickly to start using one of the soltuions that Aaron Fischer gave in the long term.
/// <summary>
/// WCF can not cope with a method that returns an object so wrap the
/// untyped object in a typed object. Then use KnowType to tell WCF
/// about the typs that are wrapped
/// </summary>
[DataContract(), KnownType(typeof(MyType1)), KnownType(typeof(MyType2))]
public class UntypedObjectHolder
{
[DataMember()]
private object m_Value;
public UntypedObjectHolder(object value)
{
m_Value = value;
}
public object Value
{
get { return m_Value; }
}
}
Then in my interface
[OperationContract()]
UntypedObjectHolder GetValue(eGetValueType valueType);
Another option that may work that I did not try is
[ServiceContract]
[ServiceKnownType(typeof(PhotoCamera))]
[ServiceKnownType(typeof(TemperatureSensor))]
[ServiceKnownType(typeof(DeviceBase))]
public interface IHomeService
{
[OperationContract] IDevice GetInterface();
}
The February 2011 Issue of the MSDN Magazine contains "Known Types and the Generic Resolver" that shows a good solution to this.
精彩评论