Tomasz emailed me a good question today:
"Very good reading about IntermediateSerializer. I was wondering however if this is possible to use it to serialize a Collection of elements which shall be serialized as shared resources. When I use [ContentSerializer(SharedResource = true)] for a Collection the collection itself is treated as a shared resource. This is a problem since I could end up with multiple "copies" of objects serialized, some of them as shared resources and some of them in the collection."
First the bad news: there is no way to do this using attributes.
But the good news is you can do it by making a custom class for your list of shared resources:
class SharedResourceList<T> : List<T> { }
and then implementing a custom ContentTypeSerializer for this new class:
[ContentTypeSerializer] class SharedResourceListSerializer<T> : ContentTypeSerializer<SharedResourceList<T>> { static ContentSerializerAttribute itemFormat = new ContentSerializerAttribute() { ElementName = "Item" };
protected override void Serialize(IntermediateWriter output, SharedResourceList<T> value, ContentSerializerAttribute format) { foreach (T item in value) { output.WriteSharedResource(item, itemFormat); } }
protected override SharedResourceList<T> Deserialize(IntermediateReader input, ContentSerializerAttribute format, SharedResourceList<T> existingInstance) { if (existingInstance == null) existingInstance = new SharedResourceList<T>(); while (input.MoveToElement(itemFormat.ElementName)) { input.ReadSharedResource(itemFormat, (T item) => existingInstance.Add(item)); } return existingInstance; } }
With the above code, this test:
SharedResourceList<string> test = new SharedResourceList<string>();
test.Add("elf"); test.Add("23"); using (XmlWriter writer = XmlWriter.Create("out.xml"))
IntermediateSerializer.Serialize(writer, test, null);
produces this XML:
<?xml version="1.0" encoding="utf-8"?> <XnaContent> <Asset Type="SharedResourceList[string]"> <Item>#Resource1</Item> <Item>#Resource2</Item> </Asset> <Resources> <Resource ID="#Resource1" Type="string">elf</Resource> <Resource ID="#Resource2" Type="string">23</Resource> </Resources> </XnaContent>
2010 note: this article describes how to customize IntermediateSerializer XML. To do the same thing for binary .xnb serialization, see here.