On Tuesday, 3 May 2022 at 10:48:53 UTC, bauss wrote:
Object.factory calls TypeInfo_Class.find which just loops through ModuleInfo and then looks if any of the entries in localClasses has a name that matches.

Afterwards it calls the create function on the TypeInfo_Class which of course isn't "generic" by any means.

This is where compile-time has its limits compared to runtime type creation, because templates only live during compile-time then it isn't really that easy to do something like this, where it would be trivial in other languages like C#.

On Tuesday, 3 May 2022 at 12:46:56 UTC, Adam D Ruppe wrote:
On Tuesday, 3 May 2022 at 09:42:45 UTC, cc wrote:
something I can pass to `Object.factory`.

Object.factory is useless and will hopefully be removed someday.

Instead, make your own factory registration function.

Put a static constructor in the class which appends a factory delegate to an array or something you can use later. Then you can use your own thing to construct registered objects.

Yeah, that's unfortunate. Actually I was already doing something similar for serialization/encoding to get the true type of an object (making sure `Animal an = new Cat();` encodes a Cat and not an Animal), took me a second to put two and two together and realize I could just instantiate objects via new that way instead of calling Object.factory.

At the moment I try to register as many relevant symbols as I can automatically when encoding is called for a given object, such as:
```d
private mixin template RegisterModule(alias MOD) {
        void RegisterModule() {
                static foreach (SYM; getSymbolsByUDA!(MOD, Coder)) {
                        static if (is(SYM == class)) {
                                RegisterSerializer!SYM();
                        }
                }
        }
}
private static void[0][string] registeredModules;

private void registerModules(T)() {
        enum string MODULENAME = moduleName!T;
        if (MODULENAME !in registeredModules) {
                registeredModules.require(MODULENAME);
                mixin("import "~MODULENAME~";");
                mixin("mixin RegisterModule!"~MODULENAME~";");
                RegisterModule();
        }
}
IPtr encode(T)(T obj) {
        registerModules!T;
        ...
}
```

I'll have to get a little more creative for registering templated classes then, something like this works:
```d
static void RegisterSerializer(alias SYM)(string runtimeName = null) {
        enum sym = fullyQualifiedName!SYM;
        if (sym !in serialTypes) {
                auto st = new SerialType!SYM;
                serialTypes[sym] = st;
                if (runtimeName.length && runtimeName !in serialTypes)
                        serialTypes[runtimeName] = st;
        }
}
static void RegisterSerializer(T : Object)(T obj) {
        RegisterSerializer!T(typeid(obj).name);
}
```
but I'd rather not have to instantiate an actual object just to get its typeid().name, I suppose I can just manually construct it from the fullyQualifiedName inserting the parenthesis and appended portion so it matches.

Reply via email to