A Tiny Little Problem…
Recently I had to implement (de)serialization support in Java and C# for an XML format defined in a set of (mutually dependent) XSD files with circular group references. In Java my weapon of choice for source code generation is Castor, and as usual it worked seamlessly after writing binding files (to handle the inter XSD dependencies and element name clashes). On .NET however, I ran into problems.
First I tried to use xsd.exe, which is shipped with Microsoft Visual Studio 2009 (.NET 3.5 SP1) but it complained that:
Group 'Foo' from targetNamespace='http://Bar' has invalid definition: Circular group reference.
Next off I searched the web and tried a couple of GUI based XML tools. Not much luck either. Many of the tools crashed right away (I later learned that several of them are nothing but GUI front-ends for xsd.exe (wrt. code generation)), while others entered seemingly infinite loops (they did terminate, but I strongly suspect it was because the loops were programmed to terminate after a fixed maximum number of iterations).
After more than a little frustration with this, perhaps not trivial but at least common, code generation task I turned to Mono (version 2.2) and tried its version of xsd.exe. This time xsd.exe didn’t crash and it seems as if it handled the circular group references satisfactorily. However, my XSDs define multiple elements with the same name (but different types and contexts), which xsd.exe didn’t like at all.
Fearing I had to (waste precious time and) code the (de)serialization support by hand I was willing to search the web for quite a while before giving up and eventually I found a solution that worked. In fact it had been right in front of me all the time.
…and a Solution
Since Castor is so good at what it does one obvious solution is, of course, to translate the source code generated by Castor to C#. A priori this seemed like a daunting task, because it would require me to translate the source code for all the dependencies of my generated code as well (the generated code depends on Castor and Castor depends on several other components, with dependencies of their own). Fortunately there is an easier way! Just translate the Java bytecode of the compiled source code (along with the compiled versions of all its dependencies) to .NET bytecode (a.k.a. CIL).
On recommendation of a friend I decided to try IKVM for this task – and it worked! Here is what I did:
1. Use Castor‘s source code generator to generate (de)serialization support for the XML format.
2.a. Compile the source files and build one big jar file containing the class files for the generated code as well as all the dependencies.
2.b. Make sure everything works.
3. Use ikvmc.exe to translate the jar from (2.a) to a .NET dll.
4. Include the dll from (3) along with IKVM.OpenJDK.ClassLibrary.dll in your C# project.
5. Call the (de)serializer from C# in exactly the same way as you would have from Java.
That was easy, wasn’t it.