views:

226

answers:

1

I have an array called _updatedComponents of objects that are of class NetworkComponent. I have to serialize it in the way that the name and namespace of the root element (=array) is changed and individual NetworkComponent-item's name is changed to component. I have a code below that causes an enception:

System.InvalidOperationException: There was an error reflecting type 'ComponentSyncService.NetworkComponent[]'. ---> System.InvalidOperationException: XmlRoot and XmlType attributes may not be specified for the type ComponentSyncService.NetworkComponent[].

    XmlAttributeOverrides xaos = new XmlAttributeOverrides();

    // the array itself aka the root. change name and namespace
    XmlElementAttribute xea = new XmlElementAttribute(_updatedComponents.GetType());
    xea.Namespace = "http://www.xxx.com/nis/componentsync";
    xea.ElementName = "components";

    XmlAttributes xas = new XmlAttributes();
    xas.XmlElements.Add(xea);
    xaos.Add(_updatedComponents.GetType(), xas); 

    // then the items of the array. just change the name
    xea = new XmlElementAttribute(typeof(networkcomponent));
    xea.ElementName = "component";

    xas = new XmlAttributes();
    xas.XmlElements.Add(xea);
    xaos.Add(typeof(NetworkComponent), "NetworkComponent", xas);

    XmlSerializer serializer = new XmlSerializer(_updatedComponents.GetType(), xaos);

    XmlTextWriter writer = new XmlTextWriter(string.Format("{0}\\ComponentSyncWS_{1}.xml", 
                          Preferences.FileSyncDirectory, requestId), Encoding.UTF8);
    serializer.Serialize(writer, _updatedComponents);

Cheers & BR: Matti

+1  A: 

What is _updatedComponents ? I'm guessing it is a NetworkComponent[] - which will make things very tricky. I would suggest writing a wrapper type:

public class ComponentsMessage {
    public NetworkComponent[] Components {get;set;}
}

Then you can associate the correct attributes. If you need to support ad-hoc attributes on NetworkComponent you'd still need to use attribute-overrides (hence I haven't decorated the above at all), but ComponentsMessage should be happy to take the attributes.

Alternately, just write a separate DTO and map the values.

If it is simple, you might just be able to use:

[XmlRoot("components", Namespace = XmlNamespace)]
[XmlType("components", Namespace = XmlNamespace)]
public class ComponentsMessage
{
    public const string XmlNamespace = "http://www.xxx.com/nis/componentsync";
    [XmlElement("component")]
    public NetworkComponent[] Components { get; set; }
}

Alternatively, if you must use attribute-overrides, I'd still use a wrapper object:

public class ComponentsMessage
{
    public NetworkComponent[] Components { get; set; }
}
class Program
{
    static void Main()
    {
        NetworkComponent[] _updatedComponents = new NetworkComponent[2] {
            new NetworkComponent{},new NetworkComponent{}
        };
        const string XmlNamespace = "http://www.xxx.com/nis/componentsync";
        XmlAttributeOverrides ao = new XmlAttributeOverrides();
        ao.Add(typeof(ComponentsMessage), new XmlAttributes {
            XmlRoot = new XmlRootAttribute("components") { Namespace = XmlNamespace },
            XmlType = new XmlTypeAttribute("components") { Namespace = XmlNamespace }
        });
        ao.Add(typeof(ComponentsMessage), "Components", new XmlAttributes {
            XmlElements =  {
                new XmlElementAttribute("component")
            }
        });
        ComponentsMessage msg = new ComponentsMessage { Components = _updatedComponents };
        XmlSerializer serializer = new XmlSerializer(msg.GetType(), ao);
        serializer.Serialize(Console.Out, msg);
    }
}
Marc Gravell
thanks for your answer! as I state in my question: "I have an array called _updatedComponents of objects that are of class NetworkComponent." I'm just leaving the work so I try it tomorrow. Too bad that it's tricky. I didn't fully understand why...
matti
thanks again! i'll check your edited answer 1st thing in the morning.
matti
i tried the simple version and it worked. thanks a lot! u put a lot of effort to provide also the XmlAttributeOverrides version. Hope it will help someone else that really needs it.
matti