www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Object.factory

reply Arlen <arlen.albert gmail.com> writes:
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
parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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
next sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
 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
parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
dennis luehring wrote:
 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???

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-Sauls
Jun 07 2007
prev sibling parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
Deewiant Wrote:

 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.

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!
Sep 25 2007
parent reply Sean Kelly <sean f4.ca> writes:
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
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Sean,

 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?
 

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

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; }
Sep 25 2007
next sibling parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
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
next sibling parent reply BCS <ao pathlink.com> writes:
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
parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
BCS Wrote:

 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

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. =DanO
Sep 25 2007
parent reply Sean Kelly <sean f4.ca> writes:
DanO wrote:
 BCS Wrote:
 
 Reply to DanO,


 MyDict!(int).classinfo.name == "MyDict!(int).MyDict";
 // Why the extra .MyDict appended to the end??

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

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.

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; Sean
Sep 26 2007
parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
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;
 
 
 Sean

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. 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
parent reply Sean Kelly <sean f4.ca> writes:
DanO wrote:
 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;

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.

Sounds like it. It would be nice if the compiler at least registered templates declared in the same module they are defined. Sean
Sep 26 2007
parent Dan Struthers <dsstruthers nospamplease.yahoo.com> writes:
Sean Kelly Wrote:

 DanO wrote:
 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;

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.

Sounds like it. It would be nice if the compiler at least registered templates declared in the same module they are defined. Sean

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? =DanO
Sep 27 2007
prev sibling parent Sean Kelly <sean f4.ca> writes:
DanO wrote:
 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??

Because that's the actual name of the class. The common declaration format is just short-hand for: template MyDict(T) { class MyDict {} } Sean
Sep 26 2007
prev sibling next sibling parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
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
parent Max Samukha <samukha voliacable.com.removethis> writes:
On Wed, 26 Sep 2007 01:42:30 -0400, DanO
<dsstruthers nospamplease.yahoo.com> wrote:

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

class MyDict(T) { } is a shorthand for template MyDict(T) { class MyDict { } }
Sep 25 2007
prev sibling parent Sean Kelly <sean f4.ca> writes:
BCS wrote:
 Reply to Sean,
 
 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?

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

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; }

So call: ClassInfo.find( parseTree.type ).create(); Sean
Sep 26 2007
prev sibling parent reply DanO <dsstruthers nospamplease.yahoo.com> writes:
Sean Kelly Wrote:

 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

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. -DanO
Sep 25 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
DanO wrote:
 Sean Kelly Wrote:
 
 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?

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

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

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. -- Daniel
Sep 25 2007
parent reply Max Samukha <samukha voliacable.com.removethis> writes:
On Wed, 26 Sep 2007 16:40:21 +1000, Daniel Keep
<daniel.keep.lists gmail.com> wrote:

DanO wrote:
 Sean Kelly Wrote:
 
 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?

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

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

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

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); }
Sep 26 2007
parent Sean Kelly <sean f4.ca> writes:
Max Samukha wrote:
 On Wed, 26 Sep 2007 16:40:21 +1000, Daniel Keep
 <daniel.keep.lists gmail.com> wrote:
 
 DanO wrote:
 Sean Kelly Wrote:

 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?

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

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

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

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?

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. Sean
Sep 26 2007