2009-03-25 16 views
12

Szukam budowania usługi WCF, która może przechowywać/pobierać wiele różnych typów. jest następujący przykład wykonalną i również za dopuszczalne design:Polimorfizm w 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; 

} 

Podczas korzystania z usługi, to muszę być w stanie przekazać typy podrzędne do metody StoreObject i otrzymać je z powrotem jako swojego rodzaju dziecko z RetrieveObject metoda.

Czy są lepsze opcje?

Dzięki Rob

Odpowiedz

17

Twój przykład nie będzie kompilować, ponieważ interfejsy nie może zawierać pola, co jest, co ObjectID, StringOne i StringTwo są. To, co próbujesz zdefiniować za pomocą IObject, IOne i ITwo, to umowa danych, a nie umowa o świadczenie usług. Jako taki powinieneś używać atrybutu DataContract, a nie atrybutu ServiceContract i klas, a nie interfejsów.

[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; 
} 

Należy zauważyć, że są to klasy, a nie interfejsy. Atrybut DataContract zastąpił atrybut ServiceContract. Atrybut KnownType zastąpił atrybut ServiceKnownType. To jest bardziej kanoniczne z tego, co widziałem.

Twoja umowa usługa będzie wówczas zdefiniowane tak:

[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); 
} 

można umieścić ServiceKnownType atrybuty na poziomie umowy (tj pod atrybutem ServiceContract) mieć ona zastosowanie do wszystkich operacji umowy.

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

    [OperationContract] 
    Guid StoreObject(MyObject NewObject); 
} 

Ty może użytku interfejsy w swoich umowach danych takie jak to:

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

Jednak interfejs IEmployee nie jest uwzględniony w eksportowanym metadanych. Więc jeśli użyjesz svcutil do wygenerowania klas proxy, twoi klienci nie będą wiedzieć o IEmployee. Nie jest to wielka sprawa, jeśli twoja usługa i klient znajdują się w tej samej aplikacji (co jest dobrym sposobem na komunikację między domenami aplikacji). Jeśli jednak twój klient jest oddzielony od twojej usługi (w przeważającej większości przypadków będzie), staje się to problematyczne, ponieważ będziesz musiał ręcznie zduplikować interfejs IEmployee po stronie klienta.

+0

Czy można podać konkretny przykład wykorzystania interfejsu IEmployee, o którym wspomniałeś, z funkcją WCF? – Kenci

+0

@Matt Davis, jedno jest brak :) Może jakiś kawałek xml? –