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:
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:
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.