digitalmars.D - Object.factory
- Arlen (34/34) Jun 07 2007 There was the 'factory' static method introduced in D some time ago. I h...
- Deewiant (11/62) Jun 07 2007 You need to specify the fully qualified name, i.e. precede "MyClass" wit...
- dennis luehring (3/7) Jun 07 2007 and why not just
- Chris Nicholson-Sauls (7/20) Jun 07 2007 If "MyClass" were being stored as a string somewhere, being selected by
- DanO (13/80) Sep 25 2007 I have found that this works quite well for non-templated classes, but t...
- Sean Kelly (7/25) Sep 25 2007 Try calling:
- BCS (9/40) Sep 25 2007 pickling?
- DanO (10/23) Sep 25 2007 Yes, pickling it is. I call it serialization, but having just started l...
- BCS (15/18) Sep 25 2007 template are scopes. Thus this
- DanO (4/31) Sep 25 2007 I forgot about the whole shorthand thing...thanks for the refresher.
- Sean Kelly (6/36) Sep 26 2007 You will need to generate the code for any template you want to generate...
- DanO (6/14) Sep 26 2007 Just so everyone knows, all of the templates I am trying to dynamically ...
- Sean Kelly (4/14) Sep 26 2007 Sounds like it. It would be nice if the compiler at least registered
- Dan Struthers (15/32) Sep 27 2007 I have found some more interesting tidbits:
- Sean Kelly (7/33) Sep 26 2007 Because that's the actual name of the class. The common declaration
- DanO (10/23) Sep 25 2007 Yes, pickling it is. I call it serialization, but having just started l...
- Max Samukha (13/36) Sep 25 2007 I guess the reason for the naming is that
- Sean Kelly (4/49) Sep 26 2007 So call:
- DanO (4/34) Sep 25 2007 Your solution doesn't help, since I really need to be able to use the cl...
- Daniel Keep (12/48) Sep 25 2007 This seems to be a limitation with templated classes, so have you tried
- Max Samukha (21/69) Sep 26 2007 It seems like a compiler bug. Classes from instantiated templates do
- Sean Kelly (4/63) Sep 26 2007 If I had to guess, I'd say it's because templates can be instantiated
There was the 'factory' static method introduced in D some time ago. I haven't been succeeding in creating a single instance of any of my classes. The result of the function call is always 'null'. What's going on? An example code: --------------------------------------------- import std.stdio; alias char[] string; int main(string[] args) { MyClass a = cast(MyClass) Object.factory("MyClass"); if(a !is null) { a.name = "Arlen"; a.family_name = "Keshabyan"; writefln(a.name ~ " " ~ a.family_name); } else writefln("cannot create the MyClass class instance!"); } class MyClass { private: string m_name; string m_family_name; public: this() { m_name = ""; m_family_name = ""; } string name(){return m_name;} void name(string value){m_name = value;} string family_name(){return m_family_name;} void family_name(string value){m_family_name = value;} }
Jun 07 2007
Arlen wrote:There was the 'factory' static method introduced in D some time ago. I haven't been succeeding in creating a single instance of any of my classes. The result of the function call is always 'null'. What's going on? An example code: --------------------------------------------- import std.stdio; alias char[] string; int main(string[] args) { MyClass a = cast(MyClass) Object.factory("MyClass"); if(a !is null) { a.name = "Arlen"; a.family_name = "Keshabyan"; writefln(a.name ~ " " ~ a.family_name); } else writefln("cannot create the MyClass class instance!"); } class MyClass { private: string m_name; string m_family_name; public: this() { m_name = ""; m_family_name = ""; } string name(){return m_name;} void name(string value){m_name = value;} string family_name(){return m_family_name;} void family_name(string value){m_family_name = value;} }You need to specify the fully qualified name, i.e. precede "MyClass" with the module name and a period. For instance, if your code is in a file called foo.d, or you have a "module foo;" in the code, pass "foo.MyClass" to Object.factory. Note that if you know the class name at compile time, you don't need Object.factory: you can use a mixin statement instead, which works just as you'd expect and without runtime costs: mixin("MyClass a = new MyClass;"); -- Remove ".doesnotlike.spam" from the mail address.
Jun 07 2007
Note that if you know the class name at compile time, you don't need Object.factory: you can use a mixin statement instead, which works just as you'd expect and without runtime costs: mixin("MyClass a = new MyClass;");and why not just MyClass a = new MyClass; why is there a need for mixin the code???
Jun 07 2007
dennis luehring wrote:If "MyClass" were being stored as a string somewhere, being selected by deep versioning or by some other compile-time process (like CTFE), then the mixin method becomes rather useful. const CLAZZ = elaborateCTF() ; mixin("auto a = new " ~ CLAZZ ~ ";"); -- Chris Nicholson-SaulsNote that if you know the class name at compile time, you don't need Object.factory: you can use a mixin statement instead, which works just as you'd expect and without runtime costs: mixin("MyClass a = new MyClass;");and why not just MyClass a = new MyClass; why is there a need for mixin the code???
Jun 07 2007
Deewiant Wrote:Arlen wrote:I have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported? Thanks!There was the 'factory' static method introduced in D some time ago. I haven't been succeeding in creating a single instance of any of my classes. The result of the function call is always 'null'. What's going on? An example code: --------------------------------------------- import std.stdio; alias char[] string; int main(string[] args) { MyClass a = cast(MyClass) Object.factory("MyClass"); if(a !is null) { a.name = "Arlen"; a.family_name = "Keshabyan"; writefln(a.name ~ " " ~ a.family_name); } else writefln("cannot create the MyClass class instance!"); } class MyClass { private: string m_name; string m_family_name; public: this() { m_name = ""; m_family_name = ""; } string name(){return m_name;} void name(string value){m_name = value;} string family_name(){return m_family_name;} void family_name(string value){m_family_name = value;} }You need to specify the fully qualified name, i.e. precede "MyClass" with the module name and a period. For instance, if your code is in a file called foo.d, or you have a "module foo;" in the code, pass "foo.MyClass" to Object.factory. Note that if you know the class name at compile time, you don't need Object.factory: you can use a mixin statement instead, which works just as you'd expect and without runtime costs: mixin("MyClass a = new MyClass;"); -- Remove ".doesnotlike.spam" from the mail address.
Sep 25 2007
DanO wrote:I have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 25 2007
Reply to Sean,DanO wrote:pickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }I have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 25 2007
BCS Wrote:pickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }Yes, pickling it is. I call it serialization, but having just started learning Python, pickling works, too. As I stated earlier, standard objects work just fine when using Object.factory() or ClassInfo.find().create(). It's template classes that are the issue. Either method returns null. I think it has something to do with the ClassInfo.name for the templated class. class MyDict(T) : ISerial { T[char[]] dict; void load(InStream s); void save(OutStream s); } MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end?? =DanO
Sep 25 2007
Reply to DanO,MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end??template are scopes. Thus this class Foo(t) { } is short hand for this template Foo(t) { class Foo { } } and D lets you implicitly reference the only member of a template if it has the same name as the template it's self. However the correct name is the whole thing
Sep 25 2007
BCS Wrote:Reply to DanO,I forgot about the whole shorthand thing...thanks for the refresher. It still doesn't solve my problem. It still can't seem to find a template class' ClassInfo via ClassInfo.find() or Object.factory(). Has anyone else seen this issue? Thanks in advance. =DanOMyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end??template are scopes. Thus this class Foo(t) { } is short hand for this template Foo(t) { class Foo { } } and D lets you implicitly reference the only member of a template if it has the same name as the template it's self. However the correct name is the whole thing
Sep 25 2007
DanO wrote:BCS Wrote:You will need to generate the code for any template you want to generate via Object.factory by aliasing or instantiating it at compile-time. Otherwise, the code won't even exist in your app. This should do the trick: alias MyDict!(int) GenerateMyDict_int; SeanReply to DanO,I forgot about the whole shorthand thing...thanks for the refresher. It still doesn't solve my problem. It still can't seem to find a template class' ClassInfo via ClassInfo.find() or Object.factory(). Has anyone else seen this issue? Thanks in advance.MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end??template are scopes. Thus this class Foo(t) { } is short hand for this template Foo(t) { class Foo { } } and D lets you implicitly reference the only member of a template if it has the same name as the template it's self. However the correct name is the whole thing
Sep 26 2007
Sean Kelly Wrote:You will need to generate the code for any template you want to generate via Object.factory by aliasing or instantiating it at compile-time. Otherwise, the code won't even exist in your app. This should do the trick: alias MyDict!(int) GenerateMyDict_int; SeanJust so everyone knows, all of the templates I am trying to dynamically create are declared and instantiated in the same module where they are defined, and all of the ones I am trying to instantiate are used somewhere in the module, usually as members of other classes. I have tried every conceivable permutation of things to get it to work, but it just looks like those classes are not in the ModuleInfo. Probably a compiler issue. As a workaround, I have made up a mixin that registers a loader function with my SerializationManager class that it can fall back on if Object.factory() fails to locate a "factory" for the type. It's kind of funky, but it works. This approach, or any for that matter, relies on both sides of the serialization stream to have instantiated each version of the template in order for the serialization to work properly. Normally that wouldn't be an issue, since two sides of a stream are usually running the same version of software, but in the case of serializing out to file, the reader could be anyone or any version. I guess that's where serialization versioning comes in.... =DanO
Sep 26 2007
DanO wrote:Sean Kelly Wrote:Sounds like it. It would be nice if the compiler at least registered templates declared in the same module they are defined. SeanYou will need to generate the code for any template you want to generate via Object.factory by aliasing or instantiating it at compile-time. Otherwise, the code won't even exist in your app. This should do the trick: alias MyDict!(int) GenerateMyDict_int;Just so everyone knows, all of the templates I am trying to dynamically create are declared and instantiated in the same module where they are defined, and all of the ones I am trying to instantiate are used somewhere in the module, usually as members of other classes. I have tried every conceivable permutation of things to get it to work, but it just looks like those classes are not in the ModuleInfo. Probably a compiler issue.
Sep 26 2007
Sean Kelly Wrote:DanO wrote:I have found some more interesting tidbits: <code> MyDict(T) { T[char[]] dict; } alias MyDict!(int) MyDictInt; auto o1 = MyDict!(int).classinfo.create(); // fails to compile with "undefined identifier MyDict.classinfo" // but auto o2 = MyDictInt.classinfo.create(); // works fine </code> So, it does look like there are some compiler or parser problems with getting at the template's ClassInfo directly, as well as it not getting inserted into the ModuleInfo.localclasses. I wonder if they may be related... Walter, do you have any insight here? Should I add a bug for this? =DanOSean Kelly Wrote:Sounds like it. It would be nice if the compiler at least registered templates declared in the same module they are defined. SeanYou will need to generate the code for any template you want to generate via Object.factory by aliasing or instantiating it at compile-time. Otherwise, the code won't even exist in your app. This should do the trick: alias MyDict!(int) GenerateMyDict_int;Just so everyone knows, all of the templates I am trying to dynamically create are declared and instantiated in the same module where they are defined, and all of the ones I am trying to instantiate are used somewhere in the module, usually as members of other classes. I have tried every conceivable permutation of things to get it to work, but it just looks like those classes are not in the ModuleInfo. Probably a compiler issue.
Sep 27 2007
DanO wrote:BCS Wrote:Because that's the actual name of the class. The common declaration format is just short-hand for: template MyDict(T) { class MyDict {} } Seanpickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }Yes, pickling it is. I call it serialization, but having just started learning Python, pickling works, too. As I stated earlier, standard objects work just fine when using Object.factory() or ClassInfo.find().create(). It's template classes that are the issue. Either method returns null. I think it has something to do with the ClassInfo.name for the templated class. class MyDict(T) : ISerial { T[char[]] dict; void load(InStream s); void save(OutStream s); } MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end??
Sep 26 2007
BCS Wrote:pickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }Yes, pickling it is. I call it serialization, but having just started learning Python, pickling works, too. As I stated earlier, standard objects work just fine when using Object.factory() or ClassInfo.find().create(). It's template classes that are the issue. Either method returns null. I think it has something to do with the ClassInfo.name for the templated class. class MyDict(T) : ISerial { T[char[]] dict; void load(InStream s); void save(OutStream s); } MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end?? =DanO
Sep 25 2007
On Wed, 26 Sep 2007 01:42:30 -0400, DanO <dsstruthers nospamplease.yahoo.com> wrote:BCS Wrote:I guess the reason for the naming is that class MyDict(T) { } is a shorthand for template MyDict(T) { class MyDict { } }pickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }Yes, pickling it is. I call it serialization, but having just started learning Python, pickling works, too. As I stated earlier, standard objects work just fine when using Object.factory() or ClassInfo.find().create(). It's template classes that are the issue. Either method returns null. I think it has something to do with the ClassInfo.name for the templated class. class MyDict(T) : ISerial { T[char[]] dict; void load(InStream s); void save(OutStream s); } MyDict!(int).classinfo.name == "MyDict!(int).MyDict"; // Why the extra .MyDict appended to the end?? =DanO
Sep 25 2007
BCS wrote:Reply to Sean,So call: ClassInfo.find( parseTree.type ).create(); SeanDanO wrote:pickling? MyTreeType BuildTree(char[] name) { auto parseTree = parse(std.file.read(name)); auto ret = cast(MyTreeType)Object.create(parseTree.type); ret.Stuff(parseTree.data) return ret; }I have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 26 2007
Sean Kelly Wrote:DanO wrote:Your solution doesn't help, since I really need to be able to use the class name to instantiate the object. I am doing serialization and I don't know the object's class. I have tried the ClassInfo.find(str).create() approach, and the doesn't work either. I'm sure Object and ClassInfo are using the same database. Whatever the problem, I was just trying to remove the need to register my own factory function for those types, but unless someone replies with some more help, I will just use my tried and true method. -DanOI have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 25 2007
DanO wrote:Sean Kelly Wrote:This seems to be a limitation with templated classes, so have you tried non-templated? class TDict!(T) { ... } class IntDict : TDict!(int) { mixin TDict!(int).ctors; } auto instance = Object.factory("IntDict"); This might be a pain in the arse, but it might work. The other thing to remember is that TDict *does not* generate any code. Only specific instances do. So even if you could instantiate a templated class via Object.factory, you'd still likely need to manually specify a finite list of classes that should be instantiated. -- DanielDanO wrote:Your solution doesn't help, since I really need to be able to use the class name to instantiate the object. I am doing serialization and I don't know the object's class. I have tried the ClassInfo.find(str).create() approach, and the doesn't work either. I'm sure Object and ClassInfo are using the same database. Whatever the problem, I was just trying to remove the need to register my own factory function for those types, but unless someone replies with some more help, I will just use my tried and true method. -DanOI have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 25 2007
On Wed, 26 Sep 2007 16:40:21 +1000, Daniel Keep <daniel.keep.lists gmail.com> wrote:DanO wrote:It seems like a compiler bug. Classes from instantiated templates do not get added to localClasses array of ModuleInfo. What is the reason for that? import std.stdio; import std.moduleinit; class C(T) { } void main(char[][] args) { foreach (m; ModuleInfo.modules()) { foreach (c; m.localClasses) { writefln(c.name); } } auto c = new C!(int); }Sean Kelly Wrote:This seems to be a limitation with templated classes, so have you tried non-templated? class TDict!(T) { ... } class IntDict : TDict!(int) { mixin TDict!(int).ctors; } auto instance = Object.factory("IntDict"); This might be a pain in the arse, but it might work. The other thing to remember is that TDict *does not* generate any code. Only specific instances do. So even if you could instantiate a templated class via Object.factory, you'd still likely need to manually specify a finite list of classes that should be instantiated. -- DanielDanO wrote:Your solution doesn't help, since I really need to be able to use the class name to instantiate the object. I am doing serialization and I don't know the object's class. I have tried the ClassInfo.find(str).create() approach, and the doesn't work either. I'm sure Object and ClassInfo are using the same database. Whatever the problem, I was just trying to remove the need to register my own factory function for those types, but unless someone replies with some more help, I will just use my tried and true method. -DanOI have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 26 2007
Max Samukha wrote:On Wed, 26 Sep 2007 16:40:21 +1000, Daniel Keep <daniel.keep.lists gmail.com> wrote:If I had to guess, I'd say it's because templates can be instantiated anywhere, but their 'home' is the module in which they are defined. SeanDanO wrote:It seems like a compiler bug. Classes from instantiated templates do not get added to localClasses array of ModuleInfo. What is the reason for that?Sean Kelly Wrote:This seems to be a limitation with templated classes, so have you tried non-templated? class TDict!(T) { ... } class IntDict : TDict!(int) { mixin TDict!(int).ctors; } auto instance = Object.factory("IntDict"); This might be a pain in the arse, but it might work. The other thing to remember is that TDict *does not* generate any code. Only specific instances do. So even if you could instantiate a templated class via Object.factory, you'd still likely need to manually specify a finite list of classes that should be instantiated. -- DanielDanO wrote:Your solution doesn't help, since I really need to be able to use the class name to instantiate the object. I am doing serialization and I don't know the object's class. I have tried the ClassInfo.find(str).create() approach, and the doesn't work either. I'm sure Object and ClassInfo are using the same database. Whatever the problem, I was just trying to remove the need to register my own factory function for those types, but unless someone replies with some more help, I will just use my tried and true method. -DanOI have found that this works quite well for non-templated classes, but templated classes don't seem to behave. I am using the ClassInfo's name property to get the string, and that doesn't work. <code> class TDict(T) { T[char[]] dict; } char[] tInfoName = TDict!(int).classinfo.name; // returns TDict!(int).TDict Object o = Object.factory(tInfoName); // returns null </code> I have not tried 'Object.factory("TDict!(int)")'; it may work just fine. Anyone have any idea if this is supposed to work or is supported?Try calling: TDict!(int).classinfo.create(); Instead. ClassInfo also has a static find(char[]) method to perform lookups without going through Object. Personally, I've never seen a reason to have the Obejct.factory() method, given what's in ClassInfo. Sean
Sep 26 2007