I've faced the need to implement an IdlUnion data type
in .Net client to interoperate with existing server
based on VisiBroker.
Unfortunately, there is not too much information on
IdlUnion neither in IIOP.NET Documentation nor Forums,
so my only source of information was source code. I
also suppose some big changes were done to IdlEnum
handling between 1.8.0 version and most recent 1.9.0beta2.
As far as i understand, the current approach to
deserialise a user's data type marked with [IdlUnion]
attribute is this (at least this is the actual
execution flow i've observed):
10 IIOP.NET tries to locate an instance, non-public
field "m_discriminator" and assign discriminator value
to it. So the user class should declare the following
member:
private Type m_discriminator;//where Type is an
integral value type
ref:
Serializer.cs:IdlUnionSerializer.GetDiscriminatorField()
20 Then it tries to locate a static, non-public method
"GetFieldForDiscriminator", that, as it expects, should
return FieldInfo of a field corresponding to a given
discriminator:
private static FieldInfo GetFieldForDiscriminator(Type
discriminator);
ref:
Serializer.cs:IdlUnionSerializer.GetValFieldForDiscriminator()
30 Finally, IIOP.NET tries to locate a non-static,
non-public field "m_initalized" of type bool, to which
it then assigns the result of deserialisation operation:
private bool m_initalized;
ref: Serializer.cs:IdlUnionSerializer.GetInitalizedField()
Of course, i, as a user, declared none of the above
members thus got an exception on a first [10] operation.
Now, here is how i would expect IdlUnion handling to
work from a User (my) perspective:
10 User marks struct to represent the union with
[UdlUnion] (note: .Net framework has no built-in
support for unions).
20 User declares enum type which enumerates all
possible values of the union [10].
30 The first field of the struct is of just declared
enum type [20]
40 Every next single field of struct [10] represents a
possible value of the union.
Having aLL this in mind, i've implemented a quick
fall-back solution (call it Patch from no on) to
deserialise IdlUnion data represented in a form above.
Here how it works:
10 First, if user struct doesn't contain
"m_discriminator" field, then, instead of throwing
exception right a way, Patch tries to discover if the
first field is of type Enum. And if it actually is,
then set a flag "m_discrIsEnum" and returns this field.
20 Next, if user struct doesn't, as well, contain any
traces of GetFieldForDiscriminator and m_discrIsEnum is
set, then Patch gets an array of struct's fields and
tries to get one of them by discriminator value as an
index.
30 Finally, if there is no "m_initalized" field in a
user's struct, but "m_discrIsEnum" was set at [10],
then Patch just supress throwing exception.
Period.
One flaw i see already in my solution is that it
blindly relies on the order in which FieldInfo's are
returned by Type.GetFields(), despite that MSDN says it
to be a bad idea. But it seems IIOP.NET relies on this
now and then. It would be interesting to know the
motivation behind this.
Simplified IdlUnion deserialisation