8

I have the following code:

private static string FindAppointmentsAsXmlString(CalendarView calendar, ExchangeService serv)
{
    FindItemsResults<Appointment> 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();
}

When initializing serializer, I get the exception:

To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy.

Microsoft.Exchange.WebServices.Data.FindItemsResults does not implement Add(System.Object).

I've searched around, and I've come to the conclusion that I have to add a public Add(Object obj) method. Now I'm not really sure what this method should contain or when it is called, can anyone point me in the right direction? Does the Add method need to manually add each appointment?

Some links I found helpful: here here

Much appreciated.

Palle Due
  • 5,929
  • 4
  • 17
  • 32
LKB
  • 1,020
  • 5
  • 22
  • 46

3 Answers3

4

The Add() method should have a single argument of the type of the elements in the IEnumerable object. For example, if FindItemsResults implements IEnumerable<T> then you can add method void Add(T value). If you want FindItemsResults to be read-only, you could convert FindItemsResults to a List via the ToList() extension method and serialize the list rather than the FindItemsResults object itself.

Jesse Sweetland
  • 1,594
  • 11
  • 10
  • I've converted the FindItemsResults appointments to a List and serialized that instead. However, now I'm getting an exception: **Microsoft.Exchange.WebServices.Data.Appointment cannot be serialized because it does not have a parameterized constructor**. Any ideas? – LKB May 30 '13 at 23:18
  • You're probably getting this error because something in the FindItemsResults object graph isn't directly serializable with XmlSerializer. You could try DataContractSerializer, which is a bit more robust, or coverting the FindItemsResultsobject graph into a simpler format (POCO DTOs) – Jesse Sweetland May 31 '13 at 02:31
1

You need to implement an Add method that can put an object of the type your IEnumerable contains back into the IEnumerable when you deserialize your FindItemsResult and the objects contained yielded by it. An IEnumerable is not like a List, so a deserialized item cannot generically just be put back into a container of some sort. There is no way to know how one may implement a class that implements IEnumerable, therefor you must explicitly write an Add method for it.

Kent Munthe Caspersen
  • 5,918
  • 1
  • 35
  • 34
  • I implemented the Add method as you stated, unfortunately the same exception is still raised. **Edit:** I didn't call the Add method - how would I do this? var serializer = new XmlSerializer(appointments.GetType().Add());? Nope, that doesn't work... – LKB May 30 '13 at 23:01
  • Does your add method takes an object of class Object as argument? I think the add method would be called automatically when you try to deserialize an object implementing IEnumerable. – Kent Munthe Caspersen May 31 '13 at 11:42
1

I ran into this same issue when creating a paged result object. The selected answer is basically correct but I thought I would just format it a little nicer and also add a tip of my own.

Basically I implemented the Add, but I have it just throw an exception to guide any future developers that may try to invoke it since as a result set I want to keep it read only. The serializer still works fine so it obviously never invokes Add when serializing. I may run into issues de-serializing but since this object is purely for retrieving a result set all should be good.

Here is what I added to the class that had implemented IEnumerable:

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