Help with reflections
BlitzMax Forums/BlitzMax Beginners Area/Help with reflections
| ||
Hi Everybody, I'm trying to write a function that goes through every object in a scene and saves its state (basically, it will be a project file for a game editor). Since I don't want to hard-code which fields get saved according to which kind of entity, I decided to learn to new reflection features. It works well for simple fields (int, float, string...) but I'm having trouble when the object contains a field that asks another type, like this: The big problem is: if I run into a field that contains a different type (in this example, a "TShape" object) how do I: 1 - Identify that type? 2 - Identify a specific field within that type? In my example, If I could extract the "name" field from the shape I could easily reconnect the two objects when I load the project file in the editor. Any help is appreciated! My brain is kinda numb right now... Cheers, Leo. |
| ||
Why not check Brucey's Bah.Persistence mod? |
| ||
Thank you, the serializer mod looks great! But... I fell that I'm already close to getting it working, and that I would learn more if solved that little problem. So far, I made everything in my framework from scratch, and learned a ton from doing so! So all that I really need is...how do I identify/access the type that's in a field? Thanks! |
| ||
The general approach is via recursion. You handle all the base types (int, string etc), then if you've got an object type left, recurse. I mentioned Brucey's mod as the code is all there - and it's one of the few recursive Reflection code samples I've seen that properly handles circular references. TTypeId has a Name() method. Some snippets: Local object_id:TTypeId=TTypeId.ForObject(_object:Object) ' Type name - float, int, string etc Local s_name:String = object_id.Name() If object_id.ExtendsType(ArrayTypeId) Then... If object_id.ExtendsType(TTypeId.ForName("TList")) Then... |
| ||
I tried downloading BAH.Persistence to take a look at the code, but can't find it... It's not on Brucey's page, or on the GoogleCode project page (there's no link on that one). Where can I find it? |
| ||
http://maxmods.googlecode.com/svn/trunk/ |
| ||
post deleted - was same as David. |
| ||
BTW. what is reflection? |
| ||
http://en.wikipedia.org/wiki/Reflection_%28computer_science%29 basically its just a way for a program to do stuff with its own code (functions, types and methods etc) at runtime, so from user interaction along side a scripting language etc. |
| ||
I started with the code from Mark:Type TObjectStream Method ReadObject:Object() 'read type name Local name$=_stream.ReadLine() 'find type Local id:TTypeId=TTypeId.ForName( name ) 'create new object! Local obj:Object=id.NewObject() 'restore it's fields... For Local fld:TField=EachIn id.EnumFields() 'ignore non-serializable fields If Not fld.MetaData( "serializable" ) Continue 'get type of field Local fldType:TTypeId=fld.TypeId() 'is field an object or int/float etc? If fldType.ExtendsType( ObjectTypeId ) 'field is an object - recurse fld.Set obj,ReadObject() Else 'field must be int/float etc...a 'leaf' fld.Set obj,_stream.ReadLine() EndIf Next Return obj End Method Method WriteObject( obj:Object ) 'what type of object is it? Local id:TTypeId=TTypeId.ForObject( obj ) 'write it's type name, eg: "TMyType" _stream.WriteLine id.Name() 'scan it's fields... For Local fld:TField=EachIn id.EnumFields() 'ignore non-serializable fields If Not fld.MetaData( "serializable" ) Continue 'get type of field Local fldType:TTypeId=fld.TypeId() 'is field an object or int/float etc? If fldType.ExtendsType( ObjectTypeId ) 'field is an object - recurse WriteObject fld.Get( obj ) Else 'field must be int/float etc...a 'leaf' _stream.WriteLine fld.Get( obj ).ToString() EndIf Next End Method Field _stream:TStream 'underlying stream End Type |
| ||
Thanks for the help and the code (and for making it so easy to read!). I'm putting it to good use right now. And Tin, another way of explaining reflection is: it's a feature that allows you to identify all the fields and methods inside an object. You can, for instance, expose the fields of an object that is selected by the user (some programs call that kind of view an "inspector" or "explorer"), etc. I don't blame you for not knowing it: the documentation in Bmax seems to explain it for people who already know what it does... :-P ...like many other things...those docs need a major overhaul for beginners (specially considering that Bmax is kinda marketed as "easy for beginners"). And where's the Wiki?!?!? Cheers! Leo. |