tags:

views:

136

answers:

4

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 client proxy if that makes a difference.)

+1  A: 

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.

Mark Seemann
Thanks, I read the documentation before posting the question, but it does not contain an example for when using KnowType on the return type of a method. I can only see examples of using KnonType within DataContracts
Ian Ringrose
According to the documentation, the attribute can only be used with classes and structs. In other words, you can't use it on a method - it'll simply not compile.
Mark Seemann
A: 

I'm not sure KnowType attr will work with enums as they can't be inherited?

MattC
all enums inherit from System.Enum, but enums can't inherit from other enums.
mt_serg
+1  A: 

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.

Aaron Fischer
thanks, can you point me at an example of uisng NetDataContractSerializer
Ian Ringrose
I found http://lunaverse.wordpress.com/2007/05/09/remoting-using-wcf-and-nhibernate/ helpfull and the example at http://davybrion.com/blog/2008/01/sending-nhibernate-entities-over-the-wcf-wire/ was what finaly got us working. The main thing to know is that you cannot use the visual studio autogenerated proxy class with NetDataContractSerializer
Aaron Fischer
A: 

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();
}
Ian Ringrose