digitalmars.D.learn - D RTTI?
- "H. S. Teoh" <hsteoh quickfur.ath.cx> Mar 05 2012
- Justin Whear <justin economicmodeling.com> Mar 05 2012
- Timon Gehr <timon.gehr gmx.ch> Mar 05 2012
- Jacob Carlborg <doob me.com> Mar 05 2012
- Jacob Carlborg <doob me.com> Mar 06 2012
I know D doesn't really have RTTI yet, but I'm experimenting with
"faking" it by doing something like:
class A {
string prop1;
int prop2;
...
void serialize() {
__serialize(this);
}
}
void __serialize(T)(T obj) {
writeln(typeid(obj));
foreach (name; __traits(derivedMembers, T)) {
writefln("%s = %s", name,
__traits(getMember,obj,name));
}
}
The only thing is, serialize() has to be declared in every derived
class, because T needs to be known at compile-time. Is there a way to
"automate" this? I.e., automatically insert the serialize() boilerplate
code into derived classes?
(P.S. D just took on brand new levels of cool when I realized I could
do something like this. Imagine doing this with C++ templates... ugh!
What a painful thought!)
T
--
Tech-savvy: euphemism for nerdy.
Mar 05 2012
On Mon, 05 Mar 2012 12:16:14 -0800, H. S. Teoh wrote:I know D doesn't really have RTTI yet, but I'm experimenting with "faking" it by doing something like: class A { string prop1; int prop2; ... void serialize() { __serialize(this); } } void __serialize(T)(T obj) { writeln(typeid(obj)); foreach (name; __traits(derivedMembers, T)) { writefln("%s = %s", name, __traits(getMember,obj,name)); } } The only thing is, serialize() has to be declared in every derived class, because T needs to be known at compile-time. Is there a way to "automate" this? I.e., automatically insert the serialize() boilerplate code into derived classes? (P.S. D just took on brand new levels of cool when I realized I could do something like this. Imagine doing this with C++ templates... ugh! What a painful thought!) T
The normal approach is to use a string mixin statement in each derived class: template Serializable() { enum Serializable = q{...your code here...}; } class B : A { mixin(Serializable); } Unfortunately, I don't believe there's any mechanism to order derived classes to automatically perform the mixin.
Mar 05 2012
On 03/05/2012 11:33 PM, H. S. Teoh wrote:On Mon, Mar 05, 2012 at 08:41:53PM +0000, Justin Whear wrote:On Mon, 05 Mar 2012 12:16:14 -0800, H. S. Teoh wrote:I know D doesn't really have RTTI yet, but I'm experimenting with "faking" it by doing something like: class A { string prop1; int prop2; ... void serialize() { __serialize(this); } } void __serialize(T)(T obj) { writeln(typeid(obj)); foreach (name; __traits(derivedMembers, T)) { writefln("%s = %s", name, __traits(getMember,obj,name)); } } The only thing is, serialize() has to be declared in every derived class, because T needs to be known at compile-time. Is there a way to "automate" this? I.e., automatically insert the serialize() boilerplate code into derived classes? (P.S. D just took on brand new levels of cool when I realized I could do something like this. Imagine doing this with C++ templates... ugh! What a painful thought!) T
The normal approach is to use a string mixin statement in each derived class: template Serializable() { enum Serializable = q{...your code here...}; } class B : A { mixin(Serializable); } Unfortunately, I don't believe there's any mechanism to order derived classes to automatically perform the mixin.
OK, it's a bit ugly I supopse, but I can live with that. Is there a way to tell whether or not a given class is a derived class or not? I'm using the Serializable template to insert serialize() into the class, and for derived classes I need to insert "override void serialize() ..." but for the base class I have to omit "override". How can I detect this in the template? Thanks! T
You can check typeof(this).
Mar 05 2012
On 2012-03-05 21:16, H. S. Teoh wrote:I know D doesn't really have RTTI yet, but I'm experimenting with "faking" it by doing something like: class A { string prop1; int prop2; ... void serialize() { __serialize(this); } } void __serialize(T)(T obj) { writeln(typeid(obj)); foreach (name; __traits(derivedMembers, T)) { writefln("%s = %s", name, __traits(getMember,obj,name)); } } The only thing is, serialize() has to be declared in every derived class, because T needs to be known at compile-time. Is there a way to "automate" this? I.e., automatically insert the serialize() boilerplate code into derived classes? (P.S. D just took on brand new levels of cool when I realized I could do something like this. Imagine doing this with C++ templates... ugh! What a painful thought!)
If you actually want serialization, and this was not just an example, you can use Orange: https://github.com/jacob-carlborg/orange http://www.dsource.org/projects/orange/ -- /Jacob Carlborg
Mar 05 2012
On 2012-03-06 19:17, H. S. Teoh wrote:On Tue, Mar 06, 2012 at 08:17:07AM +0100, Jacob Carlborg wrote:On 2012-03-05 21:16, H. S. Teoh wrote:I know D doesn't really have RTTI yet, but I'm experimenting with "faking" it by doing something like: class A { string prop1; int prop2; ... void serialize() { __serialize(this); } } void __serialize(T)(T obj) { writeln(typeid(obj)); foreach (name; __traits(derivedMembers, T)) { writefln("%s = %s", name, __traits(getMember,obj,name)); } }
If you actually want serialization, and this was not just an example, you can use Orange: https://github.com/jacob-carlborg/orange http://www.dsource.org/projects/orange/
For my purposes, I will eventually need to serialize only a subset of an object's properties, and only for a certain class of objects. Does Orange support selective serializations?
Yes, but by default is serializes everything you give it. Orange supports several ways of customizing the serialization. You can choose to not serialize specific fields or a whole class: class Foo { int a; int b; mixin NonSerialized!(b); // will not serialize "b" } class Foo { int a; int b; mixin NonSerialized; // will not serialize "Foo" at all } If you want to customize the serialization process in even more detail that's possible as well, by implementing the Serializable interface: class Foo : Serializable { int a; void toData (Serializer serializer, Serializer.Data key) { serializer.serialize(a, "b"); } void fromData (Serializer serializer, Serializer.Data key) { a = serializer.deserialize!(int)("b"); } } Actually, you don't need to implement the interface, it will use compile time introspection to check if the methods are available. Or the unintrusive approach: class Foo { int a; } auto dg = (Foo value, Serializer serializer, Serializer.Data key) { serializer.serialize(a, "b"); } Serializer.registerSerializer!(Foo)(dg); You can find the docs here: http://dl.dropbox.com/u/18386187/orange_docs/orange.serialization.Serializer.html In the docs, don't forget the "package" tab. -- /Jacob Carlborg
Mar 06 2012









Timon Gehr <timon.gehr gmx.ch> 