Thread overview
object.factory with template classes for serializing subclasses automatically
Sep 09, 2012
timotheecour
Sep 10, 2012
Jacob Carlborg
Sep 11, 2012
timotheecour
Sep 11, 2012
Chris Cain
Sep 11, 2012
Chris Cain
Sep 11, 2012
timotheecour
Sep 11, 2012
Chris Cain
Sep 11, 2012
Jacob Carlborg
September 09, 2012
Is there a way to use Object.factory with template classes?
eg:
----
class A(T){
    T x;
}
auto a=Object.factory("A!int");
----
Right now this fails (returns null).

Use case:
If we had this, it would GREATLY simplify serialization (eg as in the orange library) by not having to manually register subclasses of a given class, eg:
class B{}
class C:B{int x;}
B c=new C;
right now with orange, we need to register class C before calling serialization. If something like Object.factory("A!int") worked, this step could be made automatic.



September 10, 2012
On 2012-09-10 01:27, timotheecour wrote:
> Is there a way to use Object.factory with template classes?
> eg:
> ----
> class A(T){
>      T x;
> }
> auto a=Object.factory("A!int");
> ----
> Right now this fails (returns null).
>
> Use case:
> If we had this, it would GREATLY simplify serialization (eg as in the
> orange library) by not having to manually register subclasses of a given
> class, eg:
> class B{}
> class C:B{int x;}
> B c=new C;
> right now with orange, we need to register class C before calling
> serialization. If something like Object.factory("A!int") worked, this
> step could be made automatic.

I don't understand how Object.factory could help with serializing. But what would help is if we did get proper runtime reflection.

-- 
/Jacob Carlborg
September 11, 2012
> I don't understand how Object.factory could help with serializing. But what would help is if we did get proper runtime reflection.

All that'd be needed would be to have Object.factory working with templates, here's how:

----
unittest{
    class A{}
    class B{int x;}
    A a=new B;
    auto c=serialize(a);//will serialize field "x", no need to register!B
}

auto serialize(T)(T a){
    auto c=cast(SerializerBase)Object.factory("Serializer!("~typeid(a).to!string~").Serializer");
    return c.serialize(a);
}

class SerializerBase{//could also be an interface
    auto serialize(Object a){}
}

class Serializer(T):SerializerBase{
    auto serialize(Object a){
        auto b=cast(T)a;
        foreach (name; __traits(allMembers, T)) {
            //now we have access to fields of most derived type;
            //we can get the fields from base class as well.
        }
    }
}
----
I've left out details to focus on the key part. Deserialization is very similar.

So the question is: is that technically impossible or not to enhance Object.factory in such ways?


September 11, 2012
On Tuesday, 11 September 2012 at 03:18:40 UTC, timotheecour wrote:
> So the question is: is that technically impossible or not to enhance Object.factory in such ways?

Unless someone else wants to correct me, I'm going to say
technically impossible. Object.factory constructs a class at
runtime given a string of the name of the class. Templates,
however, are created at compile-time only. Basically, the
compiler creates a new type every time it sees a template being
used with new template arguments.

So, as you can imagine, there doesn't exist any object for
Object.factory to find at run time.

Technically, code like this MIGHT be possible:
---
import std.stdio;

class MyB(T) {
     this() {
         writeln("hello MyB!(" ~ T.stringof ~")");
     }
}

void main() {
     // create the actual type at compile-time
     Object b = Object.factory(MyB!int.classinfo.name);
     writeln("b = ", b);
}
---

In this case, the type (I'd think) is actually created at
compile-time, so it actually exists so that Object.factory can
get it. However, the code you showed in your previous post (just
purely existing in the string) could never work.
September 11, 2012
On Tuesday, 11 September 2012 at 03:18:40 UTC, timotheecour wrote:
> auto serialize(T)(T a){
>     auto c=cast(SerializerBase)Object.factory("Serializer!("~typeid(a).to!string~").Serializer");
>     return c.serialize(a);
> }

Also, now that I think about it, why couldn't you do this? (it's equivalent):

auto serialize(T)(T a) {
    auto c = cast(SerializerBase) new Serializer!T;
    return c.serialize(a);
}
September 11, 2012
> Also, now that I think about it, why couldn't you do this? (it's equivalent):
>
> auto serialize(T)(T a) {
>     auto c = cast(SerializerBase) new Serializer!T;
>     return c.serialize(a);
> }

that won't work with my example:
class A{}
class B:A{int x;}
A a=new B;
auto c=serialize(a); => T is A, but we want B so that serialization includes field x.


September 11, 2012
On Tuesday, 11 September 2012 at 04:47:11 UTC, timotheecour wrote:
>> Also, now that I think about it, why couldn't you do this? (it's equivalent):
>>
>> auto serialize(T)(T a) {
>>    auto c = cast(SerializerBase) new Serializer!T;
>>    return c.serialize(a);
>> }
>
> that won't work with my example:
> class A{}
> class B:A{int x;}
> A a=new B;
> auto c=serialize(a); => T is A, but we want B so that serialization includes field x.

Ah, I see now.

Well regardless, it couldn't be done so conveniently/transparently because Serializable!B wouldn't exist in the binary unless it was actually created in code.
September 11, 2012
On 2012-09-11 07:57, Chris Cain wrote:

> Ah, I see now.
>
> Well regardless, it couldn't be done so conveniently/transparently
> because Serializable!B wouldn't exist in the binary unless it was
> actually created in code.

Hence proper runtime reflection is needed. I see no way out of this.

-- 
/Jacob Carlborg