blob: f45a04ea91f957680ae31e9811943ce62a3640d3 [file] [log] [blame]
/* Create classes from their modules and names.
*
* Copyright: Copyright (C) D Language Foundation 2023
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Walter Bright, Steven Schveighoffer
* Source: $(DRUNTIMESRC core/_factory.d)
*/
module core.factory;
/**
* Create instance of class specified by the module symbol and a string
* representing the name of the class.
* The class must either have no constructors or have
* a default constructor.
* Params:
* mod = symbol representing the module that the class is in
* classname = string representing the name of the class
* Returns:
* null if failed
* Example:
* ---
* module foo.bar;
*
* class C
* {
* this() { x = 10; }
* int x;
* }
*
* void main()
* {
* auto c = cast(C)factory!(foo.bar)("C");
* assert(c !is null && c.x == 10);
* }
* ---
*/
Object factory(alias mod)(string classname)
{
foreach(cl; _getModuleClasses!mod)
{
if (cl.stringof == classname)
return cl.classinfo.create();
}
return null;
}
@system unittest
{
Object valid_obj = factory!object("Object");
Object invalid_obj = factory!object("__this_class_doesnt_exist__");
assert(valid_obj !is null);
assert(invalid_obj is null);
}
/**************************************
* Retrieve as a tuple all the types of the top level classes in the module mod.
*/
private template _getModuleClasses(alias mod) {
alias result = _AliasSeq!();
static foreach(m; __traits(allMembers, mod))
static if(is(__traits(getMember, mod, m) == class))
result = _AliasSeq!(result, __traits(getMember, mod, m));
alias _getModuleClasses = result;
}
private template _AliasSeq(TList...) { alias _AliasSeq = TList; }