Cook Computing

XML-RPC.NET and Optional Struct Members

January 15, 2003 Written by Charles Cook

I'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.