Passando collezione ricorsiva attraverso WCF
-
26-09-2019 - |
Domanda
Voglio passare un insieme abbastanza generico di dati attraverso un metodo di WCF. Il dato è fondamentalmente solo un insieme gerarchico di coppie chiave / valore, ma è annidato ad un livello arbitrario. Originariamente ho pensato di passare anche se, come una singola stringa e facendo XML o JSON o codifica simile / decodifica ad entrambe le estremità, ma dal momento che il trasporto WCF è comunque XML che sembrava un po 'sciocco, quindi spero ci sia un modo per passare attraverso "naturalmente".
Il metodo è abbastanza semplice:
[OperationContract]
void ProcessData(DataTree tree);
con:
public class DataTree : Dictionary<string, DataTree>
{
}
Il tutto compila bene, ma quando provo a fare funzionare il servizio si blocca con uno StackOverflowException sotto DataContract.GetStableName.
Ho provato a mettere un attributo [CollectionDataContract]
sulla classe DataTree
ed esplicitamente specificando tutti i nomi, ma che non sembra fare alcuna differenza.
Inoltre ho provato a mettere un [DataContract]
su di essa, ma poi viene a mancare anche prima perché Dictionary
è ISerializable
.
Tutte le idee? C'è un modo migliore per fare questo?
Soluzione 2
Come si è scoperto, un altro requisito è venuto (specificando un valore semplice per un nodo, oltre a un elenco dei bambini), così ho finito per definire un tipo di bambino per lo stesso, che sembra aver fatto WCF felice con lui :
[CollectionDataContract(IsReference = true, ItemName = "Param",
KeyName = "Name", ValueName = "Data")]
public class DataTree : Dictionary<string, DataTreeEntry>
{
}
[DataContract]
public class DataTreeEntry
{
[DataMember]
public string Value { get; set; }
[DataMember]
public DataTree Children { get; set; }
}
Altri suggerimenti
Per i grandi alberi di oggetti in passato ho serializzato i dati a me stesso di un array di byte che viene inviato su con WCF (e WCF non devono essere SOAP / XML se si dispone di WCF in entrambe le estremità), e poi deserializzati manualmente sul lato di ricezione.
In sostanza creare un Serialize(BinaryWriter writer)
e DeSerialize(BinaryReader reader)
per le classi in questione, che si serializza, e passa lo scrittore / lettore verso il basso per gli oggetti figlio per la serializzazione ricorsiva.
Si potrebbe anche considerare di usare protobuf-net per la serializzazione / deserializzazione. Sia come trasporto su chiamata WCF, o manualmente, e passando una matrice di byte sul filo.