Получить экземпляр класса по строке имени класса

Я заметил функцию Object.factory(char[] className) в D. Но она работает не так, как я надеялся; это не работает ;)

Пример:

import std.stdio;

class TestClass
{
    override string toString()
    {
        return typeof(this).stringof; // TestClass
    }
};

void main(string[] args)
{
    auto i = Object.factory("TestClass");
    if (i is null)
    {
        writeln("Class not found");
    }
    else
    {
        writeln("Class string: " ~ i);
    }
}

Я думаю, что это должно привести к сообщению: «Строка класса: TestClass», но там написано «Класс не найден».

Кто-нибудь знает, почему это происходит и как я могу это исправить?

Или мне нужно создать свою собственную фабрику классов. Например, создав класс со статическим массивом Object[string] classes; с экземплярами класса. Когда мне нужен новый экземпляр, я делаю это:

auto i = (className in classes);
if (i is null)
{
    return null;
}
return i.classinfo.create();

ИЗМЕНИТЬ:

Я использую его сейчас так (пример, это для веб-шаблона HMVC):

class Page : Controller
{
    static this()
    {
        register(Page.classinfo);
    }

    protected void registerActions()
    {
        registerAction("index", &index);
    }

    public void index()
    {
        request.response = "Page: " ~ request.params.get("pageID", "0") ~ " in format: " ~ request.params.get("format", "html");
    }
};

void main(string[] args)
{
    Route.add(
        r"page/(\d+)\.(html|json)",
        [
            1: "pageID",
            2: "format"
        ],
        [
            "controller": "page" // tell route to use page as controller class
        ]
    );
    Route.add(
        r"(\S+)/(\S+)",
        [
            1: "controller", // get controller class from uri
            2: "action" // get controller action from uri
        ]
    );

    auto request = Request.factory("/page/43.json").execute();

    // Headers and response can be accessed like this
    // Can be used in http response
    uint code = request.getCode();
    const(string[string]) headers = request.getHeaders();
    string response = request.response;
}

Такие вещи трудно сделать на С++;)


person VDVLeon    schedule 28.05.2010    source источник


Ответы (1)


Вот тот, который работает:

module irc2;

import std.stdio;

class TestClass
{
    override string toString()
    {
        return typeof(this).stringof; // TestClass
    }
};

void main(string[] args)
{
    auto i = Object.factory("irc2.TestClass");
    if (i is null)
    {
        writeln("Class not found");
    }
    else
    {
        writeln("Class string: " ~ i.toString);
    }
}

Несколько замечаний:

  1. Вы должны использовать полное имя класса. Что делать, если в вашей программе более одного «TestClass».
  2. Вы не можете добавить объект к строке; вы должны использовать toString. Это или просто используйте writefln("Class string: %s", i).
person DK.    schedule 28.05.2010
comment
Или можно перегрузить opCast(T:string) для класса, а затем объединить его самостоятельно? - person 0scar; 28.06.2010
comment
Нет, потому что i относится к типу Object, который вы не можете изменить. Проще просто //сказать//, что вы пытаетесь сделать: превратить объект в строку и соединить. Волшебство, автоматические преобразования между несвязанными типами просто напрашиваются на неприятности. - person DK.; 02.07.2010