I have a problem on serializing a class to XML. I have created a sample code that runs an shows the error. The class I want to serialize named "ContentContainer", ContentContainer has a collection of items that its type is "ContentItemBase". because my requirements I implemented these classes as follow. but when the code reaches to the part if actual serialization call, serializer throws this exception :
The type UserQuery+SpecificContentItem was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
I have searched on this problem but my requirements I can't implement the XmlInclude method that mentioned in exception message. is there any solution (Design OR Implementation Tip) for this problem and similar problems?
CODE :
void Main()
{
var item = new SpecificContentItem{ Name = "Test", Value = "TestValue" , SpecificField="TestField"};
var container = new ContentContainer();
container.Items.Add(item);
container.Name = "Test Container";
XmlSerializer ser= new XmlSerializer(typeof(ContentContainer));
StringWriter writer = new StringWriter();
ser.Serialize(writer, container);
string result = writer.ToString();
}
public abstract class ContentItemBase
{
public abstract string Name {get; set;}
public abstract string Value {get; set;}
}
public class SpecificContentItem: ContentItemBase
{
public string SpecificField {get; set;}
public override string Name {get; set;}
public override string Value {get; set;}
}
public class ContentContainer
{
public ContentContainer()
{
Items = new ContentItemCollection();
}
public string Name {get;set;}
public ContentItemCollection Items{get; set;}
}
public class ContentItemCollection : IEnumerable<ContentItemBase>
{
public SpecificContentItem SpecificItem { get; set; }
public IEnumerator<ContentItemBase> GetEnumerator()
{
if (SpecificItem != null)
yield return SpecificItem;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(Object obj)
{
if (obj is SpecificContentItem)
SpecificItem = (SpecificContentItem)obj;
}
}
Creating your serializer as:
XmlSerializer ser = new XmlSerializer(typeof(ContentContainer),
new Type[] { typeof(SpecificContentItem) });
should do the trick.
You can also add a Serialize
method to ContentContainer
class
public string Serialize()
{
var types = Items.Select(x => x.GetType()).Distinct().ToArray();
XmlSerializer ser = new XmlSerializer(typeof(ContentContainer),types);
StringWriter writer = new StringWriter();
ser.Serialize(writer, this);
return writer.ToString();
}
Since the allowed use of XmlInclude
seems to be ambiguous, I'm still going to suggest
[XmlInclude(typeof(SpecificContentItem))]
public class ContentItemCollection : IEnumerable<ContentItemBase>
{
as a possible solution. How that applies with your real world situation is a bit more difficult to tell, but I hope it's applicable and works!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.