Обработка модулей и классов (динамическое связывание) - PullRequest
0 голосов
/ 12 апреля 2011

Я столкнулся с небольшой проблемой, и я ищу лучшую концепцию / теорию решения.

У меня есть система, которая должна использовать объекты.Каждый объект, который использует система, имеет известный интерфейс, вероятно, реализованный как абстрактный класс.Интерфейсы известны во время сборки и не изменятся.Точная реализация будет варьироваться, и я заранее не знаю, какой модуль будет ее предоставлять.Единственная гарантия, что они предоставят интерфейс.Имя класса и модуль (DLL) взяты из файла конфигурации или могут быть изменены программно.

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

struct ClassID
{
    Module * module;
    int number;
};

class Module
{
    HMODULE module;
    function<void * (int)> * createfunc;

    static Module * Load(String filename);

    IObject * CreateClass(int number)
    {
        return createfunc(number);
    }
};

class ModuleManager
{
    bool LoadModule(String filename);

    IObject * CreateClass(String classname)
    {
        ClassID class = AvailableClasses.find(classname);
        return class.module->CreateObject(class.number);
    }

    vector<Module*> LoadedModules;
    map<String, ClassID> AvailableClasses;
};

Модули имеют несколько экспортируемых функций для определения количества классов, которые они предоставляют, и имен / идентификаторов тех, которые затем сохраняются.Все классы являются производными от IObject, который имеет виртуальный деструктор, хранит исходный модуль и имеет несколько методов для получения идентификатора класса, какой интерфейс он реализует и тому подобное.

Единственная проблема с этим - каждый модульдолжен быть где-то загружен вручную (указан в конфигурационном файле, на данный момент).Я хотел бы избежать этого в явном виде (за исключением ModuleManager, внутри которого я не особо обеспокоен тем, как это реализовано).

Я хотел бы иметь подобную систему без необходимости обрабатывать загрузкумодули просто создают объект, и (после того, как он все настроен) он волшебным образом появляется.

Я полагаю, что это в некоторой степени похоже на то, что COM должен делать.Я кратко посмотрел на систему COM, но, похоже, это было слишком сложно.Мне нужны только классы, известные в моей системе, и не нужны все остальные функции, которые она обрабатывает, только реализации интерфейсов, поступающих откуда-то.

Другая моя идея - использовать реестр и хранить ключ со всемиизвестные / зарегистрированные классы и их исходные модули и числа, так что я могу просто посмотреть их, и окажется, что Manager::CreateClass находит и делает объект волшебным образом.Это кажется жизнеспособным решением, но я не уверен, что оно оптимально или я что-то заново изобретаю.

Итак, после всего этого мой вопрос: как с этим справиться?Существует ли существующая технология, если нет, то как лучше ее настроить?Есть ли какие-то ошибки, на которые мне стоит обратить внимание?

Ответы [ 2 ]

1 голос
/ 13 апреля 2011

COM очень вероятно, что вы хотите. Он очень широкий, но вам не нужно использовать всю функциональность. Например, вам не нужно требовать от участников регистрировать GUID, вы можете определить свой собственный механизм для создания экземпляров интерфейсов. Существует ряд шаблонов и других механизмов, облегчающих создание COM-интерфейсов. Более того, поскольку это стандарт, легко документировать требования.

Одна очень важная вещь, которую следует иметь в виду, заключается в том, что для импорта / экспорта объектов C ++ требуется, чтобы все участники использовали один и тот же компилятор. Если вы думаете, что это когда-либо может быть проблемой для вас, вам следует использовать COM. Если вы рады принять это ограничение, вы можете продолжать в том же духе.

1 голос
/ 13 апреля 2011

Я не знаю, существует ли какая-либо технология для этого.

Я знаю, что я работал с системой, очень похожей на эту.Мы использовали XML-файлы для описания различных классов, которые были доступны для разных модулей.Наш эквивалент ModuleManager будет анализировать xml-файлы, чтобы определить, что создавать для пользователя во время выполнения, на основе предоставленного им имени класса и конфигурации системы.(Запрос объекта, в котором реализован интерфейс «I», может вернуть любой из объектов «A», «B» или «C» в зависимости от того, как была настроена система.)

Большая ошибка, которую мы обнаружили, заключалась в том, чтосистема была очень хрупкой и порой трудной для отладки / понимания.Просто читая код, часто было почти невозможно увидеть, какой конкретный класс был создан.Мы также обнаружили, что поддержание XML привело к большему количеству ошибок и накладных расходов, чем ожидалось.

Если бы мне пришлось сделать это снова, я бы сохранил шаблон проектирования, предоставляющий классы из DLL через интерфейсы, но я бы не стал пытаться создаватьцентральный реестр классов, и я бы не стал выводить все из базового класса, такого как IObject.

Вместо этого я бы возложил на каждый модуль ответственность за предоставление своих собственных фабричных функций для создания объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...