"XML attributes may not be specified for the type"
XmlSerializer and CollectionBase derived classes
I get this error when I try to serialize an object that is based upon the CollectionBase class and has an XmlRoot attribute.
The solution is to provide hints in the Serialization method to add a defined root in the generated XML. Thanks to user "armanddp" http://dotnet.org.za/armand/archive/2004/09/21/4164.aspx, I have beautified his solution as shown below:
Step 1: Create an attribute class that you can use to specifiy the root attribute.
[AttributeUsage(AttributeTargets.Class)]
public class XmlRootNameAttribute : Attribute
{
public XmlRootNameAttribute()
{}
public XmlRootNameAttribute(string name)
{
this.name = name;
}
public string name = string.Empty;
}
Step 2: Add the attribute to your own class.
[Serializable]
[XmlRootName("StepClassConfigurationCollection")]
public class MyCollection : CollectionBase, IList
{}
Step 3: Create a Serializer method to read the extra attribute, if it exists, otherwise serialise as per normal.
/// <summary>
/// Serialize the given object into a string
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public string SerializeObject(object o)
{
string ret = string.Empty;
Stream writer = new MemoryStream();
XmlSerializer ser = null;
XmlRootAttribute ra = new XmlRootAttribute();
Type objectType = o.GetType();
// determines if the custom attribute was found
bool bAttFound = false;
ra.Namespace = string.Empty;
// try and find the custom attribute that will determine the root namespace.
object [] oAtt = objectType.GetCustomAttributes(typeof(PMPDO.XmlRootNameAttribute), false);
if (oAtt != null)
{
if (oAtt.Length > 0)
{
bAttFound = true;
// use the given root name
ra.ElementName = ((PMPDO.XmlRootNameAttribute)oAtt[0]).name;
}
}
if (!bAttFound)
{
// if there is no root name provided, then just use the default
ser = new XmlSerializer(objectType);
}
else
{
// otherwise use the provided root name
ser = new XmlSerializer(objectType, ra);
}
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
if (bAttFound)
{
// use the given root when provided
ser.Serialize(writer, o, ns);
}
else
{
// otherwise use the default (no root provided)
ser.Serialize(writer, o);
}
// read the string from the serialized stream
writer.Position = 0;
StreamReader sr = new StreamReader(writer,System.Text.Encoding.ASCII);
ret = sr.ReadToEnd();
return ret;
}
0 comments:
Post a Comment
I always welcome feedback from my readers.