Skip to content

Interfaces und abstrakte Klassen als Parameter – Teil 2

Gestern habe ich im ersten Teil ein Problem geschildert, das auftritt, wenn man versucht Polymorphismus im Zusammenhang mit WCF-Services einzusetzen. Dabei ging es konkret darum Interfaces oder abstrakte Klassen als Parameter an Service-Methoden zu übergeben.

Die vorgestellte Lösung für das Problem mittels des ServiceKnownType-Attributs hatte den Nachteil, dass "echter" Polymorphismus nicht unterstützt wurde und somit ein weiteres Problem geschaffen war bzw. das eigentlich Problem nicht richtig gelöst war.

Um in unserem Beispiel "echten" Polymorphismus zu unterstützen, muss es möglich sein, beliebige Instanzen von Klassen an den Service zu übermitteln, die entweder das Interface ICustomer implementieren oder von der abstrakten Klasse CustomerBase abgeleitet sind. Möglich ist dies durch den Einsatz des NetDataContractSerializers. Wie das im Detail funktioniert beschreibt Aaron Skonnard in seinem Blogeintrag WCF's NetDataContractSerializer.
Mit Hilfe des dort vorgestellten NetDataContractFormat-Attributs sieht die Beschreibung unseres Service somit folgendermaßen aus:

C#:
  1. [ServiceContract]
  2. public interface ICustomerService
  3. {
  4.     [OperationContract]
  5.     [NetDataContractFormat]
  6.     void AddCustomerInterface(ICustomer customer);
  7.  
  8.     [OperationContract]
  9.     [NetDataContractFormat]
  10.     void AddCustomerBase(CustomerBase customer);
  11. }

OK, alles ist super. Polymorphismus wird unterstützt und wir sind glücklich.

Naja, leider nicht wirklich ...
Wer den Beitrag von Aaron Skonnard aufmerksam gelesen hat, dem sollte klar sein, dass dieser Ansatz dem Grundsatz der Serviceorientierung widerspricht. Ein Java-Client wird beispielsweise mit diesem Service nicht mehr kommunizieren können. Ihm fehlen schlichtweg die Informationen über Typen (genauer die XML Schema Definitionen), die bei der Methode mittels ServiceKnownType-Attribut bereits gestellt wurden.
Wenn wir für unseren Services die ServiceMetadataBehaviour-Eigenschaft HttpGetEnabled aktivieren, bestätigt ein Blick in die automatisch generierte WSDL diesen Umstand. Die nachfolgend dargestellten komplexen Typen SimpleCustomer und ExtendedCustomer werden nämlich nicht mehr generiert.

XML:
  1. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" ...>
  2.     <xs:complexType name="SimpleCustomer">
  3.         <xs:complexContent mixed="false">
  4.             <xs:extension base="tns:CustomerBase">
  5.                 <xs:sequence />
  6.             </xs:extension>
  7.         </xs:complexContent>
  8.     </xs:complexType>
  9.     <xs:element name="SimpleCustomer" nillable="true"
  10.         type="tns:SimpleCustomer" />
  11.     <xs:complexType name="CustomerBase">
  12.         <xs:sequence>
  13.             <xs:element minOccurs="0" name="name"
  14.                 nillable="true" type="xs:string" />
  15.         </xs:sequence>
  16.     </xs:complexType>
  17.     <xs:element name="CustomerBase" nillable="true"
  18.         type="tns:CustomerBase" />
  19.     <xs:complexType name="ExtendedCustomer">
  20.         <xs:complexContent mixed="false">
  21.             <xs:extension base="tns:CustomerBase">
  22.                 <xs:sequence>
  23.                     <xs:element minOccurs="0"
  24.                         name="customerID"
  25.                         nillable="true"
  26.                         type="xs:string" />
  27.                 </xs:sequence>
  28.             </xs:extension>
  29.         </xs:complexContent>
  30.     </xs:complexType>
  31.     <xs:element name="ExtendedCustomer"
  32.         nillable="true" type="tns:ExtendedCustomer" />
  33. </xs:schema>

Aber keine Sorge, auch für dieses Problem gibt es eine Lösung in Teil 3.

Nachtrag: Nicholas Allen gibt in seinem Blog einen wichtigen Hinweis, warum das NetDataContractFormat-Attribut nicht angewendet werden sollte. Der Grund ist, dass die Beschreibung des Services verändert wird, was laut diesem MSDN Eintrag zu unbestimmten Verhalten führt.

Categories: Programming, Web.

Tags: , , , , ,

Comment Feed

2 Responses



Some HTML is OK

or, reply to this post via trackback.

Continuing the Discussion

  1. [...] Das Spiel lässt sich nahezu unendlich so weiter spielen. Eine Lösung dafür gibt es in Teil 2. [...]

  2. [...] Lösung für ein Problem bin ich noch schuldig geblieben. Die beim letzten mal vorgestellte Lösung hatte den Nachteil, dass ein wichtiges Prinzip der Serviceorientierung [...]