2012-12-20 6 views
7

Używamy klasy bazowej dla wszystkich naszych DTO Response w naszej aplikacji. Klasa ma następujący podpis:WCF Klasa abstrakcyjna bazy z złożonym zbiorem typów abstrakcyjnych, które nie są uwzględniane do deserializacji w odpowiedzi na usługi

[Serializable] 
public abstract class ResponseBase 
{ 
    public bool Successful { get; set; } 
    public List<ResponseMessage> Messages { get; set; } 

    //...Other code... 
} 

Zbiór wiadomości mogą być dowolne z następujących typów:

[Serializable] 
[XmlInclude(typeof(DebugMessage))] 
[XmlInclude(typeof(InfoMessage))] 
[XmlInclude(typeof(ValidationMessage))] 
[XmlInclude(typeof(WarnMessage))] 
[XmlInclude(typeof(RecoverableFaultMessage))] 
[XmlInclude(typeof(FatalFaultMessage))] 
public abstract class ResponseMessage 
{ 
    //..Other code... 
} 

betonem wersjach:

[Serializable] 
public class DebugMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.Debug; } } 
} 
[Serializable] 
public class InfoMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.Info; } } 
} 
[Serializable] 
public class ValidationMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.Validation; } } 
} 
[Serializable] 
public class WarnMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.Warn; } } 
} 
[Serializable] 
public class RecoverableFaultMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.RecoverableFault; } } 
} 
[Serializable] 
public class FatalFaultMessage : ResponseMessage 
{ 
    public override MessageType MessageType { get { return MessageType.FatalFault; } } 
} 
obiekty Response

Wszystko DTO dziedziczyć ResponseBase jednak nawet z następującymi ServiceKnownTypes na kontrakcie WCF

[ServiceKnownType(typeof(ResponseBase))] 
[ServiceKnownType(typeof(ResponseMessage))] 
[ServiceKnownType(typeof(List<ResponseMessage>))] 
[ServiceKnownType(typeof(DebugMessage))] 
[ServiceKnownType(typeof(InfoMessage))] 
[ServiceKnownType(typeof(ValidationMessage))] 
[ServiceKnownType(typeof(WarnMessage))] 
[ServiceKnownType(typeof(RecoverableFaultMessage))] 
[ServiceKnownType(typeof(FatalFaultMessage))] 
[ServiceKnownType(typeof(List<DebugMessage>))] 
[ServiceKnownType(typeof(List<InfoMessage>))] 
[ServiceKnownType(typeof(List<ValidationMessage>))] 
[ServiceKnownType(typeof(List<WarnMessage>))] 
[ServiceKnownType(typeof(List<RecoverableFaultMessage>))] 
[ServiceKnownType(typeof(List<FatalFaultMessage>))] 

Kiedy załadować wiadomość do kolekcji ResponseBase Wiadomości następujące pobiera wyjątek:

Błąd w linii 1 pozycja 906. Element „http://schemas.datacontract.org/2004/07/ CX.Framework.Common.BaseTypes: ResponseMessage " zawiera dane z typu, który odwzorowuje na nazwę " http://schemas.datacontract.org/2004/07/CX.Framework.Common.BaseTypes:WarnMessage ". Deserializator nie ma żadnej wiedzy o dowolnym typie mapującym do tej nazwy. Rozważ użycie DataContractResolver lub dodaj typ odpowiadający "WarnMessage" do listy znanych typów - na przykład za pomocą atrybutu KnownTypeAttribute lub dodając go do listy znanych typów przekazanych do DataContractSerializer.

Zrobiliśmy wszystko, od ServiceKnownType do XMLInclude na typach pochodnych. Jestem trochę zagubiony, jak rozwiązać ten problem i byłbym wdzięczny za pomoc, którą każdy może zapewnić.

+2

Spróbuj wprowadzić znane atrybuty typów dla ResponseMessage w definicji klasy ResponseBase. Robię podobnie (używając '[DataContract]' i '[KnownType]') i wymaga to, aby klasa, która ma członków typu polimorficznego, była dekorowana '[KnownType (typeof (DerivedTypeA))]'. –

+0

Powinien opublikować jako odpowiedź @flem! To właśnie zadziałało i było pierwszą odpowiedzią na pytanie, uderzeniem w komentarz, ale dziękuję za odpowiedź. – VulgarBinary

+0

Przyjemność ... Tu nie chodzi tylko o przedstawiciela! ;) –

Odpowiedz

5

kilka rzeczy:

1) [XmlInclude] będą miały żadnego wpływu na DataContractSerializer, jest używany tylko przez XmlSerializer.

2) Jako komentarz "flem" zasugerowałem, użyłbym [KnownType] bezpośrednio na ResponseMessage zamiast [ServiceKnownType] w usłudze.

3) Nie pamiętam, czy DataContractSerializer szuka nawet typów [KnownType] na [Serializable]. Przynajmniej na razie do celów testowych, spróbuj zamiast tego tworzyć typy [DataContract] (i przypisz dane członkom za pomocą [DataMember]), jeśli powyższe # 2 nie pomoże.

+1

# 2 działało, # 3 nie. Ponieważ moja edycja nie została zatwierdzona, umieszczę ją tutaj, ponieważ najwyraźniej ktokolwiek ją niezatwierdził, nie chce, aby szybkie i łatwe było określenie działającego rozwiązania dla przechodniów. – VulgarBinary

Powiązane problemy