More on reflection: how do I handle an object type

BlitzMax Forums/BlitzMax Beginners Area/More on reflection: how do I handle an object type

Leo Santos(Posted 2008) [#1]
Hello all. I've made progress with the reflection examples you guys provided last time I was stuck, but now I'm running into a new problem.

Let's say I have a function that creates a new object from a string containing a type name, like this:



That works fine, but there's a catch: the object returned is an "object" type. Let's say I need a "Tentity" type that I created, and I use the above function to retrieve it from a text file, and I put it in a list.

As soon as I try to access a field in it (like the field "name", that belongs to the Tentity type) the compiler complains, saying it can't find it. In other words, if I create a "Tentity" type directly, I can access its fields just fine, but if I create it using the above function, the compiler doesn't seem to understand that it is a "Tentity" type (or whatever type), not an "object" type

If that's not clear I can post the entire code, but it's quite long.

Thanks in advance!
Leo.


Perturbatio(Posted 2008) [#2]
I'm not up on reflection in BMax, but do you need to cast the result as a TEntity?


plash(Posted 2008) [#3]
Simple,
Import brl.reflection
Import sidesign.minib3d

Local obj:Object
Local typ:String = "TEntity"
	obj = CreateNew(typ)
	
If TEntity(obj)
  Local ent:TEntity = TEntity(obj)
	
	ent.name = "An Entity"
	Print ent.name
	
EndIf

Function CreateNew:Object(ObjType:String) 

  'Creates a new object based on a string containing the desired Type 
  Local id:TTypeId = TTypeId.ForName(ObjType) 
	
	If id
	   Return id.NewObject()
	
	Else
	   Return Null
		'P.S. This line will never get printed, because you have it after return :P
		Print ("Object type  " + ObjType + " is not recognized") 
		
	EndIf
	
End Function



Leo Santos(Posted 2008) [#4]
Hmmmm....so I'd have to handle the type outside the function, is that right?

If so, that could create problems down the line! Imagine that, in the future, I add a new object type to my little engine, a "TWindow" instead of "Tentity", for instance. Every time I add something like that, I would have to revise the engine code to handle it, wouldn't I?

Is there a way to avoid that, keeping it generic enough so any type can be handled without the need to hardcode how the engine deals with it?

I'm at work now, so I can't play with it, but thanks! I'll take a look when I get home!


Paposo(Posted 2008) [#5]
Hello.

mmm. Is correct your aproach?
If is needed handle many objects with similar behavior is good use inheritance and make a parent type for all.
Sorry. i not explain well using english. :(

Bye,
Paposo


Difference(Posted 2008) [#6]
Hmmmm....so I'd have to handle the type outside the function, is that right?

You could also make the function less generic and then declare it like this:
Function CreateNew:TEntity (ObjType:String) 

Then cast in the return statement:
 Return TEntity(id.NewObject())


[EDIT]: It seems you know that already, but thats the way it is. Casting is always hardcoded.


plash(Posted 2008) [#7]
I don't think thats going to help him, he can already get the actual type of the object without returning it as a TEntity. I would assume he is loading more then just one kind of object.

Your just going to have to account for all the different types of objects your going to use Leo.


Leo Santos(Posted 2008) [#8]
Heh, I was probably doing something wrong somewhere else in the code, it's kind of working well now! Thanks for your help!

What I'm doing now is just returning the objects as "object" like before, but whenever I need them to be a specific object type, like the example "Tentity", I check them with "If Tentity(Obj)", and in case it's true I reference Obj to a Temp:Tentity object and do whatever I have to do in that one.

I'm only having trouble now when I try to set a value in a field that's an array, I can't figure out how to do it without reflection.bmx throwing out an esoteric "ERROR". I'm looking into Brucey's persistence module to see how he handles it, but my brain hurts!! :P

I can figure out when an object is an array (usingTTypeID.ExtendsType), but how do I figure out if a FIELD is an array?

Thanks so much!
Leo.


Leo Santos(Posted 2008) [#9]
A-ha! Figured that one out!

Local id:TTypeId = TTypeId.ForObject(CurrentObject) 
Local Fld:TField = id.FindField(FieldName) 	

If Fld._typeId.ExtendsType(ArrayTypeId) Then FieldType = "Array"

What I still haven't figured out is... how do I SET a value on a field that's an array??? I always get that damn "ERROR" from the reflection.bmx module when I try... help!!!...


Leo Santos(Posted 2008) [#10]
Found out that one too! Thanks for your Persistence source code, Brucey! Took me a while to understand it, but it helped a lot!...
Setting the field value as an array is actually so simple that it made me feel dumb:

Local MyArray:String[]
Local id:TTypeId = TTypeId.ForObject(CurrentObject) 
Local MyField:TField = id.FindField(FieldName) 

MyField.Set(CurrentObject, MyArray)

Just using the Array object directly as the value being applied to the field works!

:D