views:

49

answers:

1

I'm trying to deserialize some xml without having the original class that was used to create the object in xml. The class is called ComOpcClientConfiguration.
It's succesfully setting the ServerUrl and ServerUrlHda values, but not rest of them...
So what I'm asking is: How can I make the rest of these values get set properly, and why aren't they working with my current code.

Here is my deserialization code:
conf is an XElement which represents the ComClientConfiguration xml

DataContractSerializer ser = new DataContractSerializer(typeof(ComClientConfiguration), new Type[] {typeof(ComClientConfiguration), typeof(ComOpcClientConfiguration) });
ComOpcClientConfiguration config = (ComOpcClientConfiguration)ser.ReadObject(conf.CreateReader());

I don't know why I have to have ComClientConfiguration and ComOpcClientConfiguration, there's probably a better way to do the known types hack I have. But for now it's what I have.

Here is the xml as it looks in the file.

<ComClientConfiguration  xsi:type="ComOpcClientConfiguration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
   <ServerUrl>The url</ServerUrl>
   <ServerName>a server name   </ServerName>
   <ServerNamespaceUrl>a namespace url</ServerNamespaceUrl> 
   <MaxReconnectWait>5000</MaxReconnectWait> 
   <MaxReconnectAttempts>0</MaxReconnectAttempts> 
   <FastBrowsing>true</FastBrowsing>
   <ItemIdEqualToName>true</ItemIdEqualToName>
   <ServerUrlHda>hda url</ServerUrlHda>
 </ComClientConfiguration>

Here is the class I built to deserialize into:

[DataContract(Name = "ComClientConfiguration", Namespace = "http://opcfoundation.org/UA/SDK/COMInterop")]
public class ComClientConfiguration
{
    public ComClientConfiguration() { }

    //Prog-ID for DA-connection
    [DataMember(Name = "ServerUrl"), OptionalField]
    public string ServerUrl;//url
    [DataMember(Name = "ServerName")]
    public string ServerName;
    [DataMember(Name = "ServerNamespaceUrl")]
    public string ServerNamespaceUrl;//url
    [DataMember(Name = "MaxReconnectWait")]
    public int MaxReconnectWait;
    [DataMember(Name = "MaxReconnectAttempts")]
    public int MaxReconnectAttempts;
    [DataMember(Name = "FastBrowsing")]
    public bool FastBrowsing;
    [DataMember(Name = "ItemIdEqualToName")]
    public bool ItemIdEqualToName;

    //ProgID for DA-connection
    [DataMember, OptionalField]
    public string ServerUrlHda;//url
}

I additionally had to make this class, it's the same but with a different name. Used for known types in the Serializer because I don't know exactly how the whole type naming stuff works.

[DataContract(Name = "ComOpcClientConfiguration", Namespace = "http://opcfoundation.org/UA/SDK/COMInterop")]
public class ComOpcClientConfiguration
{
    public ComOpcClientConfiguration() { }

    ... Same innards as ComClientConfiguration
}
+1  A: 

Data-contract-serializer is... Fussy. In particular, I wonder if simply element order is the problem here. However, it is also not necessarily the best tool for working with XML. XmlSerializer is probably a more robust here - it can handle a much better range of XML. DCS simply isn't intended with that as it's primary goal.

With simple XML you often don't even need any attributes etc. You can even use xsd.exe on your existing XML to generate the matching c# classes (in two steps; XML-to-xsd; xsd-to-c#).

Marc Gravell