cancel
Showing results for 
Search instead for 
Did you mean: 

.NET assembly returning wrong object type

Former Member
0 Kudos

I am running into a problem with a .NET assembly created in Powerbuilder 12.5 classic. The code below illustrates my issue but my actual situation is more complex than this.

I have the following objects:

n_cst_base inherits from nonvisualobject

n_cst_child_a inherits from n_cst_base

n_cst_child_b inherits from n_cst_base

n_cst_grandchild_a inherits from n_cst_child_a

n_cst_base has a public function of_myname, which is overridden by each child.  Here is the code in that function:

n_cst_base: return 'I am base'

n_cst_child_a: return Super::of_myname() + ' and I am child A'

n_cst_child_b: return Super::of_myname() + ' and I am child B'

n_cst_grandchild_a:  return Super::of_myname() + ' and I am grandchild A'

I also have object n_cst_object_factory from nonvisualobject with the following method:

public function n_cst_base of_create_dynamic (string asv_childobject);

n_cst_base lnv_object

lnv_object = CREATE using asv_childobject

return lnv_object

This function returns n_cst_base but can create any object. (There is no error checking for the illustration.)

I have a .NET assembly target that exposes all these methods in namespace PJS.Test. In my Visual Studio C# project, I can add a reference. The object browser shows the inheritance correctly.

public class n_cst_base

public class n_cst_child_a : n_cst_base

public class n_cst_child_b : n_cst_base

public class n_cst_grandchild_a : n_cst_child_a

I have the following test method in C#:

public void TestObjects()

{

n_cst_object_factory oObjectFactory = new n_cst_object_factory();

n_cst_base oChildBaseB = oObjectFactory.of_create_dynamic("n_cst_child_b");

string sBName = oChildBaseB.of_myname();

Boolean IsChildB = oChildBaseB is n_cst_child_b ? true : false;

n_cst_child_b oChildB = (n_cst_child_b)oChildBaseB;

When I debug this, I can see the value of sBName = "I am base and I am child B" as expected.  However the type of oChildBaseB is n_cst_base when I expect that it would be n_cst_child_b.  The value of IsChildB is false and the cast throws an InvalidCastException. The result of of_myname indicates that the object is indeed n_cst_child_b. Why does is it typed as n_cst_base?

Again in C#, I can do the following

n_cst_base oChildBaseB = new n_cst_child_b();

string sBName = oChildBaseB.of_myname();

Boolean IsChildB = oChildBaseB is n_cst_child_b ? true : false;

n_cst_child_b oChildB = (n_cst_child_b)oChildBaseB;

In this scenario, the type of oChildBaseB is n_cst_child_b.  The IsChildB is true and the cast is successful. Why is it different when it comes out of the Powerbuilder assembly?

Is there some other solution to this? As stated above, my real application is more complex than this and there will be a large number of descendants, so it is impractical to write separate methods (of_create_child_a, of_create_child_b, etc) that return each type explicitly.

Accepted Solutions (0)

Answers (2)

Answers (2)

former_member190719
Active Contributor
0 Kudos

It's very likely that your object factory declared as returning n_cst_base.

public function n_cst_base of_create_dynamic (string asv_childobject);

n_cst_base lnv_object

lnv_object = CREATE using asv_childobject

return lnv_object

It may actually create a descendant class, but all it knows is that the object is what the function is declared to return.

However, the cast should work.  I've have to try it myself to see why not.

Former Member
0 Kudos

Thank you for the reply.

Yes my object factory is declared as returning n_cst_base. I can tell that it is actually creating the descendant class, because when I call the of_myname() function it returns the value that the child class would return.

When I call the object factory function directly in a Powerbulder application, the cast does work.  It should work the same in the assembly - right?

Former Member
0 Kudos

Hi Patti;

  If you look at the PowerBuilder Classic .Net objects, you will see that they all map to the PB System Classes and not standard C#.Net data types. Even in PB.Net, the PB System Types are inherited from the appropriate .Net classes and then everything you build (including in PB Classic) are inherited from the unique PB System Class. Thus, when you try and use a PB object in C# you will always get an invalid casting error and similarly, trying to use a C# object (or Java for that matter) will always get you into trouble with a casting error in a PB application as neither system understands the other.

  FWIW: That is why you should always and only pass standard C data types between Assemblies and/or Web Services when dealing with disparate development languages. This is, you can only pass common denominators not language specific data types.

HTH

Regards ... Chris

former_member190719
Active Contributor
0 Kudos

I'm trying to understand what your response has to do with the question.  What the OP is complaining about is that the PB assembly is reporting one PB type to be a different PB type.

Former Member
0 Kudos

Thank you for the reply. All of the objects I am dealing with descend from "nonvisualobject" which on the .NET side appears to map to System.Object. When I create the powerbuilder nvo objects in C# using "new", the casting works correctly, as shown below

n_cst_base oChildBaseB = new n_cst_child_b();

n_cst_child_b oChildB = (n_cst_child_b)oChildBaseB;

What doesn't work is when the object is returned from Powerbuilder.

n_cst_object_factory oPBObjectFactory = new n_cst_object_factory();

n_cst_base oChildBaseB = oPBObjectFactory.of_create_dynamic("n_cst_child_b");

n_cst_child_b oChildB = (n_cst_child_b)oChildBaseB; --> This gets the invalid cast exception

Here is the Powerbuilder code for of_create_dynamic in n_cst_object_factory which descends from nonvisualobject.

public function n_cst_base of_create_dynamic (string asv_childobject);

n_cst_base lnv_object

lnv_object = CREATE using asv_childobject

return lnv_object

The question is why does it throw a cast exception?