2013-05-30 24 views
5

Così ho il seguente codice:C#: Per essere XML serializzabile, tipi che ereditano da IEnumerable devono avere un'implementazione di Add (System.Object)

private static string FindAppointmentsAsXmlString(CalendarView calendar, ExchangeService serv) 
     { 
      FindItemsResults appointments = 
       serv.FindAppointments(WellKnownFolderName.Calendar, calendar);

var serializer = new XmlSerializer(appointments.GetType()); var writer = new StringWriter(); try{ serializer.Serialize(writer, appointments); Console.WriteLine(writer.GetStringBuilder().ToString()); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex); Console.ReadLine(); } return writer.GetStringBuilder().ToString(); }

Quando si inizializza serializzatore, ottengo l'eccezione:

Per essere serializzabili in XML, i tipi che ereditano da IEnumerable devono avere un'implementazione di Aggiungi (System.Object) a tutti i livelli della loro gerarchia di ereditarietà.

Microsoft.Exchange.WebServices.Data.FindItemsResults non implementa Aggiungi (System.Object).

Ho cercato in giro, e sono giunto alla conclusione che devo aggiungere un metodo pubblico Aggiungi (Object obj). Ora non sono veramente sicuro di cosa dovrebbe contenere questo metodo o quando viene chiamato, qualcuno può indicarmi la giusta direzione? Il metodo Aggiungi deve aggiungere manualmente ciascun appuntamento?

Alcuni link che ho trovato utile: here here

molto apprezzato.

risposta

3

Il metodo Add() deve avere un singolo argomento del tipo di elementi nell'oggetto IEnumerable. Ad esempio, se FindItemsResults implementa IEnumerable<T>, è possibile aggiungere il metodo void Add(T value). Se si desidera che FindItemsResults sia di sola lettura, è possibile convertire FindItemsResults in un elenco tramite il metodo di estensione ToList() e serializzare l'elenco anziché l'oggetto FindItemsResults stesso.

+0

Ah .. giusto. Ci proverò ora e tornerò da te. :) – LKB

+0

Ho convertito gli appuntamenti di FindItemsResults in una lista e li ho serializzati. Tuttavia, ora sto ottenendo un'eccezione: ** Microsoft.Exchange.WebServices.Data.Appointment non può essere serializzato perché non ha un costruttore con parametri **. Qualche idea? – LKB

+0

Probabilmente stai ricevendo questo errore perché qualcosa nel grafico dell'oggetto FindItemsResults non è serializzabile direttamente con XmlSerializer. Puoi provare DataContractSerializer, che è un po 'più robusto, o coprire il grafico FindItemsResultsobject in un formato più semplice (DTO POCO) –

1

È necessario implementare un metodo Aggiungi che può inserire un oggetto del tipo che IEnumerable contiene nuovamente in IEnumerable quando si deserializza FindItemsResult e gli oggetti contenuti da esso restituiti. Un oggetto IEnumerable non è come un elenco, quindi un oggetto deserializzato non può essere rimesso genericamente in un contenitore di qualche tipo. Non c'è modo di sapere come si possa implementare una classe che implementa IEnumerable, quindi è necessario scrivere esplicitamente un metodo Add per questo.

+0

ho implementato il metodo Add come lei ha affermato, purtroppo la stessa eccezione è ancora sollevata. ** Modifica: ** Non ho chiamato il metodo Aggiungi - come dovrei farlo? var serializer = new XmlSerializer (appointments.GetType(). Add()) ;? No, non funziona ... – LKB

+0

Il tuo metodo add prende un oggetto di classe Object come argomento? Penso che il metodo add venga chiamato automaticamente quando si tenta di deserializzare un oggetto che implementa IEnumerable. –

1

Mi sono imbattuto in questo stesso problema durante la creazione di un oggetto risultato paginato. La risposta selezionata è fondamentalmente corretta, ma ho pensato di formattarla un po 'di più e aggiungere anche un consiglio personale.

Fondamentalmente ho implementato l'aggiunta, ma ho appena lanciato un'eccezione per guidare eventuali sviluppatori futuri che potrebbero provare a invocarlo poiché come set di risultati voglio mantenerlo solo in lettura. Il serializzatore funziona ancora bene quindi ovviamente non invoca mai durante la serializzazione. Potrei imbattersi in problemi di serializzazione, ma poiché questo oggetto è puramente per il recupero di un set di risultati, tutto dovrebbe essere buono.

Ecco quello che ho aggiunto alla classe che aveva attuato IEnumerable:

public void Add(T value) 
    { 
     throw new NotSupportedException("Add is not supported for paged results. Try adding new items to the repository instead."); 
    }