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.