Board index » delphi » Object Streaming with RTTI >> A Solution

Object Streaming with RTTI >> A Solution

Hi all,
I've spent a great amount of time reading posts dealing with object
streaming but found nothing involving RTTI for more generic (non-component)
object streaming.
I have a Value Object data model with a lot of (50+) different types to
manage, and most of them have lots of properties, so I really don't want to
write a separate stream writer / reader for each (nor do I want to maintain
these methods in the future).

So I've come up with a solution in which I define a "TStreamable"
super-class containing a Save and Write methods. They do the actual
serialization by introspecting descendant objects and using TWriter and
TReader. All my 50+ objects inherit from this super-class and become de
facto streamable. Implementation is pretty simple and straighforward.

I was wondering if anyone out there had any experience with objet streaming
involving RTTI (probably, I hope) and wanted to share his point of view with
me. I'm especially interested in potential problems, burdens, limitations of
all kinds.

If you're interested in my code, drop me a note and I'll send it asap.

Cheers,

Stephane Vandenbussche
s...@myplayster.com

ps: sorry for my bad english and all that.

--
"I have made this letter longer than usual because I lack
 the time to make it shorter." -- Blaise Pascal

 

Re:Object Streaming with RTTI >> A Solution


"Stephane Vandenbussche" wrote

Quote
> So I've come up with a solution in which I define a "TStreamable"
> super-class containing a Save and Write methods. They do the actual
> serialization by introspecting descendant objects and using TWriter and
> TReader. All my 50+ objects inherit from this super-class and become de
> facto streamable. Implementation is pretty simple and straighforward.

I use ancestor RTTI introspection in my current design and it works very
well. My only general suggestion to your overall plan is not to have your
50+ persistable objects inherit from your TRTTIAncester class, but rather to
have them use it (by incorporating it as an internal object, or
creating/freeing it as needed for persistence actions).

Following this idea does cause some extra 'admin' code transferring data in
and out of the TRTTIAncester, but what you gain is
1. Good OO data containment: your objects no longer have to publish their
persistent properties openly.
2. Freedom to descend your objects from other useful classes (like, for
instance, TCollection/TCollectionItem)
3. Ability to have the public properties of your objects be
more/less/different than their persisted representatives.

Actually I don't do straight streaming (or anything else) from my core RTTI
enabled class--what's important about it is that it's runtime-iterable for
property names, types, and values. Separate adapter classes can use this to
provide binary streaming (or XML streaming, etc.).

Quote
> If you're interested in my code, drop me a note and I'll send it asap.

Sure--always love to see alternative approaches.

bobD

Re:Object Streaming with RTTI >> A Solution


Quote
"Bob Dawson" <bdaw...@idtdna.com> wrote in message news:3e2ea7e7$1@newsgroups.borland.com...
> ...
> >   a) classes should be registered with RegisterClass;
>      Unnecessary.

Really? Ok, you have a class name in a string variable.
How would you create an instance?

--
Regards
Illya Kysil, software developer
Delphi/C/C++/C#/Java/Forth/Assembler
If it is NOT SOURCE, it is NOT SOFTWARE. (C) NASA

Re:Object Streaming with RTTI >> A Solution


Quote
"Illya Kysil" <iky...@nospam.ua> wrote in message

news:3e2eca69@newsgroups.borland.com...
Quote
> "Bob Dawson" <bdaw...@idtdna.com> wrote in message

news:3e2ea7e7$1@newsgroups.borland.com...

Quote
> > ...
> > >   a) classes should be registered with RegisterClass;
> >      Unnecessary.
> Really? Ok, you have a class name in a string variable.
> How would you create an instance?

"I" wouldn't go that far...storing the class name is as much a violation of
encapsulation as direct table access.

I would have some kind of cross reference so that a system would know which
class it should be creating...but not intrinsically tied to a particular
class name.

John

Re:Object Streaming with RTTI >> A Solution


"Illya Kysil" wrote

Quote
> >      Unnecessary.
> Really? Ok, you have a class name in a string variable.
> How would you create an instance?

Depends on the circumstances that lead you to want to do that--the point is
that the ability to do it isn't an inherent feature of an RTTI-based
persistence framework.

bobD

Re:Object Streaming with RTTI >> A Solution


Thanks to all for your constructive input.

I've also looked into DECAL's SuperStream
http://sourceforge.net/projects/decal
It still asks for a lot of code in my opinion (I'm a bit lazy I must
admit...)
I don't dislike the Java flavor of it, but I think it concentrates too much
on code esthetics and theory, not enough on maintainability and automation.

To all who requested my code, I'll send it asap. It needs a bit cleaning
before distribution :)

Thanks for your time.
Stephane Vandenbussche

Re:Object Streaming with RTTI >> A Solution


"Stephane Vandenbussche" wrote

Quote

> I have D6, does anyone know if D7 has improved RTTI a bit?

Diffing the TypInfo files between 6 and 7 shows nothing major--couple of
tweaks is all.

bobD

Re:Object Streaming with RTTI >> A Solution


Have you tried my quickrtti?
http://www.bigattichouse.com/community.php

The only real drawback at present is not properly handling "cross"
references properly, but we have quite a few projects, in production
for a year or more using quickrtti.

The only code on your part is registering the objects with the Delphi
class system. QuickRTTI has a base class for talking with RTTI
(without streaming), and I implemented a streaming mechanism (which
could be adapted for many different formats, currently 3 different XML
parsers - I recommend the middlex parser)

procedure SaveObject (FileName:String;P:TPersistent);
var M:TMiddlexQuickRTTI; f:Tstringlist;
begin
 M:=TMiddlexQuickRTTI;
 f:=tstringlist.create;
 M.tagname:=P.classname;
 M.rttiobject:=P;
 f.text:=M.xml;
 f.savetofile(filename);
 M.free;
 f.free;
end;

easy enough?  store the xml into a stringlist and save to a file, and
load later:

procedure LoadObject (FileName:String;P:TPersistent);
var M:TMiddlexQuickRTTI; f:Tstringlist;
begin
 M:=TMiddlexQuickRTTI;
 f:=tstringlist.create;
 M.tagname:=P.classname;
 M.rttiobject:=P;
 f.loadfromfile(filename);
 M.xml:=f.text;
 M.free;
 f.free;
end;

If you plan to store LOTs of objects, create a "base" object as a
TCollection object or similar, and pass that into quickrtti.. it will
save all the child nodes. You base object can have a Tlist property
containing child objects. Just make sure any custom objects are
registered when your project starts (initialization section, or in the
form.create method:
  Registerclass(TCustomer);  sort of thing)

There is also a TXMLAware class, and you can have one global
RTTIenabler that all your objects can use.. then you just call save of
load!

Mike

Re:Object Streaming with RTTI >> A Solution


In Quickrtti ( http://www.bigattichouse.com ) I require registerclass
to be called so that Delphi knows about the RTTI of an object set..
works VERY well.

As for classes, you must assume that either:
a) a classname - in scope - is a unique identifier.
b) given a "namespace", each class is unique within the namespace.

I've been playing aruond with building a "mapping" system, so that
given XML could be mapped to classes without needing the classname
(currently I AM storing the classname).. so you could say "CUST"
translates to TCustomer in this application, I could force type
checking on the input and validate the input as well (making sure my
"interface" of published properties is compatible with the data coming
into it.) No one has really asked for this feature yet, so it hasn't
been a priority.

So I suppose it would be nice for a "Namespace" situation in
Registerclass, instead of a single global namespace. That might give
you your versioning.

Mike

Re:Object Streaming with RTTI >> A Solution


Quote
"Illya Kysil" <iky...@nospam.ua> wrote in message

news:3e3107a1@newsgroups.borland.com...
Quote
> "John Elrick" <jelr...@adelphia.net> wrote in message

news:3e2ed3d6@newsgroups.borland.com...

Quote
> > "I" wouldn't go that far...storing the class name is as much a violation
of
> > encapsulation as direct table access.

> > I would have some kind of cross reference so that a system would know
which
> > class it should be creating...but not intrinsically tied to a particular
> > class name.
> You should register some information which maps your OID to a class
anyway.
> This is a general limitation of Delphi runtime.

Yes...but not in the persistent store used for content.  That would have to
be stored in some kind of metadata.

John

Re:Object Streaming with RTTI >> A Solution


On Tue, 21 Jan 2003 22:18:21 -0600, "Bob Dawson" <RBDaw...@prodigy.net>
wrote:

what's "ancestor RTTI introspection"?

--
Bill Boulton
using D3 Std on a 98SE box

Re:Object Streaming with RTTI >> A Solution


Hello Stephane,

May be you should look at Spider Objects at
http://www.intervalsoftware.com/products.html including the Spider Object
Database.

Regards,
Andrew Yashchuk
Developer

Quote
"Stephane Vandenbussche" <s...@myplayster.com> wrote in message

news:3e2dd5f7@newsgroups.borland.com...
Quote
> Hi all,
> I've spent a great amount of time reading posts dealing with object
> streaming but found nothing involving RTTI for more generic
(non-component)
> object streaming.
> I have a Value Object data model with a lot of (50+) different types to
> manage, and most of them have lots of properties, so I really don't want
to
> write a separate stream writer / reader for each (nor do I want to
maintain
> these methods in the future).

> So I've come up with a solution in which I define a "TStreamable"
> super-class containing a Save and Write methods. They do the actual
> serialization by introspecting descendant objects and using TWriter and
> TReader. All my 50+ objects inherit from this super-class and become de
> facto streamable. Implementation is pretty simple and straighforward.

> I was wondering if anyone out there had any experience with objet
streaming
> involving RTTI (probably, I hope) and wanted to share his point of view
with
> me. I'm especially interested in potential problems, burdens, limitations
of
> all kinds.

> If you're interested in my code, drop me a note and I'll send it asap.

> Cheers,

> Stephane Vandenbussche
> s...@myplayster.com

> ps: sorry for my bad english and all that.

> --
> "I have made this letter longer than usual because I lack
>  the time to make it shorter." -- Blaise Pascal

Re:Object Streaming with RTTI >> A Solution


Thanks Andrew, interesting indeed.
However, it implies a bit too much code overhead to my taste. It also does
not simplify the process of streaming, it just adds wrappers for
non-Publishable data types.

I think non-Publishable data types like Arrays or Records are not an issue.
99% of my object's properties are automatically handled by my TStreamable
parent class. The 1% of leftovers is dealt with manually through two very
convenient event handlers: this is from far less work than changing all of
my containers, writing an iterator for each and typecasting my objects to
TBucketXYZ everywhere(http://www.intervalsoftware.com/spiderclasses.html)

Everyone in this discussion seems to be focussing on (mainly) component
persistence. That represents only a fraction of the mainstream of
applications out there. Most applications need objects streaming for
inter-process or inter-app data exchange. DCom, Corba and SOAP are ways to
address this issue. But if you want something lightweight or homegrown, RTTI
is the way.

I started this thread to discuss RTTI. So far I've had a lot of feed back on
architecture, object philosophy and third party solutions, but not so much
on RTTI itself.

Cheers, :)
Steph.

"Andrew Yashchuk" <ad...@foksel.ru> a crit dans le message news:
3e378...@newsgroups.borland.com...

Quote
> Hello Stephane,

> May be you should look at Spider Objects at
> http://www.intervalsoftware.com/products.html including the Spider Object
> Database.

> Regards,
> Andrew Yashchuk
> Developer

> "Stephane Vandenbussche" <s...@myplayster.com> wrote in message
> news:3e2dd5f7@newsgroups.borland.com...
> > Hi all,
> > I've spent a great amount of time reading posts dealing with object
> > streaming but found nothing involving RTTI for more generic
> (non-component)
> > object streaming.
> > I have a Value Object data model with a lot of (50+) different types to
> > manage, and most of them have lots of properties, so I really don't want
> to
> > write a separate stream writer / reader for each (nor do I want to
> maintain
> > these methods in the future).

> > So I've come up with a solution in which I define a "TStreamable"
> > super-class containing a Save and Write methods. They do the actual
> > serialization by introspecting descendant objects and using TWriter and
> > TReader. All my 50+ objects inherit from this super-class and become de
> > facto streamable. Implementation is pretty simple and straighforward.

> > I was wondering if anyone out there had any experience with objet
> streaming
> > involving RTTI (probably, I hope) and wanted to share his point of view
> with
> > me. I'm especially interested in potential problems, burdens,
limitations
> of
> > all kinds.

> > If you're interested in my code, drop me a note and I'll send it asap.

> > Cheers,

> > Stephane Vandenbussche
> > s...@myplayster.com

> > ps: sorry for my bad english and all that.

> > --
> > "I have made this letter longer than usual because I lack
> >  the time to make it shorter." -- Blaise Pascal

Re:Object Streaming with RTTI >> A Solution


Staphane -

  I am working on converting a legacy app into (hopefully) a more OOP
structure.  There's a _LOT_ I don't know about OOP, but what you
describe here:

Quote
>I have a Value Object data model with a lot of (50+) different types to
>manage, and most of them have lots of properties, so I really don't want to
>write a separate stream writer / reader for each (nor do I want to maintain
>these methods in the future).

sounds very much like what I am trying to accomplish.
This part:
Quote
>. . . introspecting descendant objects and using TWriter and TReader.

is where I am stuck at the moment, and don't know which way to turn.

Could you send me a snippet of your code?

Thanks very much,

Richard A{*word*53}er

Other Threads