XML-RPC.NET and Optional Struct Members
January 15, 2003 Written by Charles CookI've done some more thinking on the problem of handling optional struct members in XML-RPC.NET and I've come to the conclusion that although nullable types work well for simple value types such as int and boolean, they become confusing for more complex reference types such as arrays and structs.
For example, in the following struct what type could be used to represent the fact the Numbers member is optional?
struct A
{
public int[] Numbers;
}
So we do need an attribute to indicate optional members which leaves the problem discussed earlier: how do we indicate that an optional value type is missing. For example, if a response returns an XML-RPC struct and we are using the following struct to represent it, if after deserialization member Optional is zero, we don't know whether this value was actually passed in the XML-RPC struct.
[XmlRpcMissingMapping(MappingAction.Ignore)]
struct B
{
public int Optional;
}
A solution is to provide nullable types for the XML-RPC types which are mapped onto .NET value types. The following table illustrates which .NET types would be used to map XML-RPC struct member values where the members are either expected or optional. The serialization/deserialization code uses the attribute to determine whether an exception should be thrown if an expected member is missing and the application code can check the reference types for null to determine whether an optional member has been supplied.
| XML-RPC | .NET (Expected) | .NET (Optional) | ||
| int | Int32 | value | XmlRpcInt | ref |
| boolean | Boolean | value | XmlRpcBoolean | ref |
| string | String | ref | String | ref |
| double | Double | value | XmlRpcDouble | ref |
| dateTime | DateTime | value | XmlRpcDateTime | ref |
| base64 | Byte[] | ref | Byte[] | ref |
| array | Array | ref | Array | ref |
| struct (fixed) | struct | value | Derived from XmlRpcStruct | ref |
| struct (dynamic) | XmlRpcStruct | ref | XmlRpcStruct | ref |
Struct B would now look like this:
[XmlRpcMissingMapping(MappingAction.Ignore)]
struct B
{
public XmlRpcInt Optional;
}
Client code can then test for member Optional being null:
if (retStruct.Optional != null)
Console.WriteLine("The response contained member Optional");
I don't like it - its too complicated - but I think the advantage of being able to represent all XML-RPC structs accurately, rather than using hashtables, outweighs the complexity. Anyway the latter approach is always available using XmlRpcStruct.