2009-03-25 19 views
12

Estoy buscando construir un servicio WCF que pueda almacenar/recuperar una gama de diferentes tipos. es el ejemplo siguiente diseño aceptable viable y también se considera:Polimorfismo en WCF

[ServiceContract] 
public interface IConnection 
{   
    [OperationContract] 
    IObject RetrieveObject(Guid ObjectID); 

    [OperationContract] 
    Guid StoreObject(IObject NewObject); 


} 

[ServiceContract] 
[ServiceKnownType(IOne)] 
[ServiceKnownType(ITwo)] 
public interface IObject 
{ 
    [DataMember] 
    Guid ObjectID; 

} 

[ServiceContract] 
public interface IOne:IObject 
{ 
    [DataMember] 
    String StringOne; 

} 

[ServiceContract] 
public interface ITwo:IObject 
{ 
    [DataMember] 
    String StringTwo; 

} 

Al utilizar el servicio, que tendría que ser capaz de pasar los tipos del niño en el método StoreObject y recuperarlos como su tipo de Niños de la RetrieveObject método.

¿Hay mejores opciones?

Gracias, Rob

Respuesta

17

Su ejemplo no compilará porque las interfaces no pueden contener campos, que es lo que de objeto, StringOne, y son StringTwo. Lo que intenta definir con IObject, IOne e ITwo es un contrato de datos, no un contrato de servicio. Como tal, debe utilizar el atributo DataContract, no el atributo y las clases de ServiceContract, no las interfaces.

[DataContract] 
[KnownType(typeof(MyOne))] 
[KnownType(typeof(MyTwo))] 
public class MyObject 
{ 
    [DataMember] 
    Guid ObjectID; 
} 
[DataContract] 
public class MyOne : MyObject 
{ 
    [DataMember] 
    String StringOne; 
} 
[DataContract] 
public class MyTwo : MyObject 
{ 
    [DataMember] 
    String StringTwo; 
} 

Observe que se trata de clases, no de interfaces. El atributo DataContract ha reemplazado el atributo ServiceContract. El atributo KnownType ha reemplazado el atributo ServiceKnownType. Esto es más canónico por lo que he visto.

Su contrato de servicio se definiría luego como esto:

[ServiceContract] 
public interface IConnection 
{ 
    [OperationContract] 
    [ServiceKnownType(typeof(MyOne))] 
    [ServiceKnownType(typeof(MyTwo))] 
    MyObject RetrieveObject(Guid ObjectID); 

    [OperationContract] 
    [ServiceKnownType(typeof(MyOne))] 
    [ServiceKnownType(typeof(MyTwo))] 
    Guid StoreObject(MyObject NewObject); 
} 

Usted puede poner atributos de la ServiceKnownType a nivel de contrato (es decir, bajo el atributo ServiceContract) para que se aplica a todas las operaciones del contrato.

[ServiceContract] 
[ServiceKnownType(typeof(MyOne))] 
[ServiceKnownType(typeof(MyTwo))] 
public interface IConnection 
{ 
    [OperationContract] 
    MyObject RetrieveObject(Guid ObjectID); 

    [OperationContract] 
    Guid StoreObject(MyObject NewObject); 
} 

Usted puede utilizar interfaces en sus contratos de datos como este:

interface IEmployee 
{ 
    string FirstName 
    { get; set; } 
    string LastName 
    { get; set; } 
} 
[DataContact] 
class Employee : IEmployee 
{...} 

Sin embargo, la interfaz IEmployee no se incluye en los metadatos exportados. Entonces, si usa svcutil para generar sus clases de proxy, sus clientes no sabrán sobre IEmployee. Esto no es un gran problema si su servicio y el cliente residen en la misma aplicación (que es una buena forma de comunicarse entre los dominios de la aplicación). Sin embargo, si su cliente está separado de su servicio (en la gran mayoría de los casos, lo será), esto se vuelve problemático porque tendrá que duplicar manualmente la interfaz de IEmployee en el lado del cliente.

+0

¿Es posible para usted hacer un ejemplo concreto de cómo usar la interfaz de IEmployee que menciona, con WCF? – Kenci

+0

@Matt Davis, una cosa es la falta :) Tal vez alguna pieza de xml? –