4

I have a model that looks like:

[Serializable]
public class TemplatePageModel
{
    public PageModel Page { get; set; }
    public SidebarModel Sidebar { get; set; }
}

[Serializable]
public class PageModel
{
    public IEnumerable<SectionModel> Section { get; set; }
}

[Serializable]
public class SidebarModel
{
    public IEnumerable<ControlModel> Control { get; set; }
}

[Serializable]
public class SectionModel
{
    public string Order { get; set; }

    public string Editable { get; set; }

    public string Column { get; set; }

    public string Text { get; set; }
}

I'm then trying to cache this in memcached using EnyimMemcached.

No exceptions are thrown, but the item isn't stored.
I've tracked this down to the fact that my TemplatePageModel class isn't serializable.

I tested this with this little snippet:

MemoryStream mem = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
try
{
    b.Serialize(mem, result);
}
catch (Exception ex)
{
    //EXCEPTION HERE
}

It's complaining about my IEnumerable properties.

Actual error message is:

Type 'System.Linq.Enumerable+WhereSelectEnumerableIterator`2[[System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[Desktop.Service.Model.ControlModel, Dekstop.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' in Assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

How can I get round this?

I was hoping not to have to serialize into json first, and de-serialize on the way out if possible....

Alex
  • 37,502
  • 51
  • 204
  • 332
  • 1
    define "complaining". Tell us the exact message. Actually, note that `BinaryFormatter` doesn't care whether something is `IEnumerable` - it is a field-level serializer. What it *might* care about is some things not being `[Serializable]`. So: what is `.Section` and `.Control` **actually** at runtime? – Marc Gravell Jul 03 '12 at 12:51
  • sorry, edited to show actual error message now – Alex Jul 03 '12 at 12:53

1 Answers1

6

BinaryFormatter is a field-level serializer. It won't care whether something is IEnumerable etc. It just cares about: "what is the actual object here? can I serialize it?". For example, an array or list is generally serializable. Some custom deferred sequence (maybe a filtered LINQ expression) is potentially not serializable.

Perhaps an even easier option: don't try to serialize complex expressions. So instead of:

obj.Controls = someQuery.Where(x => whatever).OrderBy(x => x.Foo);

do:

obj.Controls = someQuery.Where(x => whatever).OrderBy(x => x.Foo).ToArray();

An array (or list) is simple and trivially serializable.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Yep.. was using Linq to create object from XML... wasn't calling .ToList on a where.. was causing the problem. Thanks! – Alex Jul 03 '12 at 13:15
  • I am not sure I understand correctly: The issue is because the IEnumerable might be holding a custom deferred sequence and therefore it can not be serialized? – Dzyann Dec 17 '13 at 20:44