Need example .NET for inherited types from IDL

5 posts / 0 new
Last post
Offline
Last seen: 2 years 6 months ago
Joined: 10/18/2013
Posts: 42
Need example .NET for inherited types from IDL

I see that the shapes demo has a type with a parent.  Is there source code provided for it that I am not seeing?

 

I have some inheritence in my datamodel (idl).  During some initial testing, I realize that the data, after being read, doesn't seem to contain these relationships anymore.  There must be something more i need to do before i write it/register it etc.  but I can't find any examples.  if there is .NET code I could see, that would be great.

Offline
Last seen: 3 years 1 month ago
Joined: 01/15/2013
Posts: 94

Hi Jay,

Let me see if I understand the problem. You have a type that inherits from another one, e.g.

struct InnerType {
    long longField;
};

struct OuterType: InnerType {
    double doubleField;
};

Then you generate the code with RTI DDS Gen, for C#, don't you? And the inheritance relationships are missed? That may be a type mis-registration.

Are you using the right TypeSupport class for the type registration? In the example above, for publishing the type OuterType, you would need to call OuterTypeTypeSupport.register_type().

If you know that some of your types are not going to be communicated via DDS directly, for example inner types or types used just for building main types, you can use the IDL @top-level directive (see section 3.3.8.4 in the RTI Connext Core Libraries and Utilities User's Manual). RTI DDS Gen won't generate type-support, data reader or data writer code for types marked with top-level equal to false. So, in my example above:

struct InnerType {
    long longField;
}; //@top-level false

struct OuterType: InnerType {
    double doubleField;
}; 

RTI DDS Gen will not generate specific reading/writing code for type InnerType. It will, however, generate it for OuterType, as true is the default value for @top-level and I didn't specify it.

This directive also helps preventing errors caused by inheritance and wrong type registrations.

Hope this helps clarifying and with your code.

Thanks,

Juanlu

Offline
Last seen: 2 years 6 months ago
Joined: 10/18/2013
Posts: 42

you do understand my problem, at least partially.  I did not go into enough detail initially.  I am doing what you say, generating the code with rtiddsgen for C# and my IDL is similar to your example.

 

I would like to create an OuterType1, OuterType2, ... and then put each of those into a Sequence<InnerType> (since each outertype inherits from InnerType).  Then I'd like to publish that sequence.  I'd like to sub/read that sequence and downcast each InnerType to its respective OuterType.  I've tried using C# 'as' knowing the actual type.  That does not seem to work.  Am I missing something obvious, or is this even possible?

 

Right now I'm going to reread your reply a couple of times and test what you have suggested.  I will report back, but if you have more info now, please give me your thoughts.

 

Also, I have support for Connext 5.1.  Would this be something I should use the paid support for instead of the public forum?

Gerardo Pardo's picture
Offline
Last seen: 3 weeks 1 day ago
Joined: 06/02/2010
Posts: 601

Hi Jay,

I think I understand the problem you are having.

Type inheritance in DDS is not polymorphic in the sense that the type that is actually sent on the wire is resolved according to the declared (compile-time) type rather than the actual (dynamic, run-time) type.

Assume the following type declarations similar to the situation you described:

struct InnerType {
    long longField;
};
 
struct OuterType1 : InnerType {
    // extra members
    float floatField;
};

struct OuterType2 : InnerType {
    // extra members
    double doubleField;
};

struct MyType {
    sequence<InnerType> innerTypeSeq;
};
  

In this scenario MyType is declared to have a sequence of InnerType. So even if you fill it with objects of type OuterType1 or OuterType2 (which the language will of course let you do) the objects will be serialized as being of type InnerType. You can think of this as if the "serialize" operation on the object was not declared as a virtual function.

This situation also occurs on deserialization.  All the elements in the sequence will be de-serialized according to their declared type on the receiving side.

Incidentally Connext DDS 5.1 supports the OMG DDS Extensible Type specification (DDS-XTYPES). This means that as long as the type is marked with "mutable extensibility" it is actually legal to publish a sequence<OuterType> and consume a sequence<InnerType>  and vice-versa.  However on both these situations the receiver still recontructs the data according to its declared type, so it if subscribed to InnerType and receives an OuterType it will truncate the additional members. If it subscribed to an OuterType and received an InnerType it will fill the non-received members with default values (or nil).

The reason with Connext DDS (and DDS-XTYPES) use the declared types to marshal/unmarshal rather than the actual (dynamic, run-time) types is that doing the latter would require elso marshaling the type information along with the data. This can be significant overhead in size and time.

If you really needed this capability one thing you could try is to do your own marshaling. But this gets tricky if you try to interoperate between different languages...

Can you describe more the actual application scenario/datamodel? Perhaps we can try to suggest an alternative way to map the types to get the desired behavior.

Gerardo

Offline
Last seen: 2 years 6 months ago
Joined: 10/18/2013
Posts: 42

You hit the nail on the head.  Polymorphism is the word I left out of my post that would have made the muddy water clear.


I will come back this week and describe the application/model to get your input.  In discussion since my last post we have come up with a couple of other options that should work.  We would love your input though, so I'll post again soon.


Thank you,

Charles