2012-12-20 4 views
7

Stiamo utilizzando una classe di base per tutti i nostri DTO di risposta nella nostra applicazione. La classe ha la seguente firma:WCF Classe di base astratta con raccolta complessa di tipi astratti non inclusi per la deserializzazione nella risposta di servizio

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

    //...Other code... 
} 

La collezione messaggi possono essere uno dei seguenti tipi:

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

Con le versioni concrete di:

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

Tutti DTO oggetti Response ereditano da ResponseBase tuttavia anche con i seguenti ServiceKnownTypes sul contratto 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>))] 

Quando carichiamo un messaggio nella collezione ResponseBase Messaggi la seguente eccezione si butta:

errore nella riga 1 posizione 906. Elemento 'http://schemas.datacontract.org/2004/07/ CX.Framework.Common.BaseTypes: ResponseMessage ' contiene i dati di un tipo associato al nome ' http://schemas.datacontract.org/2004/07/CX.Framework.Common.BaseTypes:WarnMessage '. Il deserializzatore non è a conoscenza di alcun tipo che esegue il mapping con questo nome. Considerare l'utilizzo di DataContractResolver o aggiungere il tipo corrispondente a "WarnMessage" all'elenco di tipi noti, ad esempio utilizzando l'attributo KnownTypeAttribute o aggiungendolo all'elenco dei tipi noti passati a DataContractSerializer.

Abbiamo eseguito tutto da ServiceKnownType a XMLInclude sui tipi derivati. Sono un po 'in perdita su come risolvere questo problema e apprezzerei l'assistenza che chiunque può fornire.

+2

Provare a inserire gli attributi di tipo noto per ResponseMessage nella definizione della classe ResponseBase. Faccio la stessa cosa (usando '[DataContract]' e '[KnownType]') e richiede che la classe che ha membri del tipo polymorphable sia decorata con '[KnownType (typeof (DerivedTypeA))]'. –

+0

Dovrebbe essere pubblicato come risposta @flem! Questo è ciò che ha funzionato ed è stata la prima risposta alla domanda, urlando sul commento ma grazie per la risposta. – VulgarBinary

+0

Piacere ... Non si tratta solo del rappresentante! ;) –

risposta

5

Un paio di cose:

1) [XmlInclude] non avrà alcun effetto sul DataContractSerializer, è usato solo dal XmlSerializer.

2) Come suggerito dal commentatore "flem", vorrei utilizzare [KnownType] direttamente su ResponseMessage anziché su [ServiceKnownType] sul servizio.

3) Non ricordo se il DataContractSerializer cerca anche [KnownType] sui tipi [Serializable]. Almeno a scopo di test per ora, prova a creare i tuoi tipi [DataContract] invece (e attribuisci i membri dei dati con [DataMember]) se il # 2 sopra non aiuta.

+1

# 2 funzionava, # 3 no. Dato che la mia modifica non è stata approvata, la inserirò qui perché apparentemente chiunque non sia approvato non vuole che sia rapida e facile determinare la soluzione di lavoro per i passanti. – VulgarBinary

Problemi correlati