C++ поддерживает множественное наследование, поэтому вы можете иметь общий API устойчивости и наследовать механизм сохранения. Это все равно должно было бы использовать интроспекцию для извлечения метаданных класса, но у вас все еще есть эта проблема с любым уровнем сохранения.
Альтернативно вы можете сделать что-то подобное, но использовать метаданные для генерации генератора кода, который заполняет «Getters» и «Setters» для слоя persistence.
Любой уровень сохранения обычно использует тот или иной подход, поэтому ваша проблема заключается в том, чтобы связать механизм загрузки с уровнем сохранения. Я думаю, что это делает вашу проблему немного отличающейся от одного слоя сохранения, но решая ее с другого направления. Вместо того, чтобы создавать классы домена в каркасе персистентности, вы предоставляете набор классов домена с помощью крючков для структуры персистентности, которые сторонние пользователи могут подключить к ним механизм доступа к данным.
Я думаю, что как только вы предоставите доступ к метаданным класса и обратным вызовам, механизм perisistence будет относительно прост. Посмотрите на компоненты метаданных любой удобной C++ структуры отображения O/R и поймите, как они работают. Инкапсулируйте это с помощью API в один из базовых классов ваших классов домена и предоставьте общий API-интерфейс getter/setter для создания или сохранения. Остальное зависит от человека, реализующего слой сохранения.
Редактировать: Я не могу придумать библиотеку C++ с типом используемого механизма переноса, который вы описываете, но я сделал что-то в Python, который мог бы добавить этот тип объекта. Конкретная реализация использовала объекты в Python без прямого эквивалента C++, хотя основной принцип, вероятно, можно было бы адаптировать для работы с C++.
В Python вы можете перехватывать обращения к переменным экземпляра, переопределяя __getattr()__
и __setattr()__
. Механизм сохранения фактически сохранил свой собственный кеш данных за кулисами. Когда функциональность была смешана с классом (выполнялась через множественное наследование), он переопределял поведение системы по умолчанию для доступа к члену и проверял, соответствует ли запрашиваемый атрибут чем-либо в его словаре. В этом случае вызов был перенаправлен для получения или установки элемента в кеше данных.
Кэш имел собственные метаданные. Он знал о взаимоотношениях между объектами в своей модели данных и знал, какие имена атрибутов перехватывают для доступа к данным. То, как это сработало, отделило его от уровня доступа к базе данных и могло (по крайней мере теоретически) позволить использовать механизм сохранения с разными драйверами.Не существует неотъемлемой причины, по которой вы не могли (например) построить драйвер, который сериализовал его в XML-файл.
Сделать что-то вроде этой работы на C++ было бы немного сложнее, и может оказаться невозможным сделать доступ к кешу объектов прозрачным, как это было с этой системой. Вероятно, вам будет лучше с явным протоколом, который загружает и удаляет состояние объекта в кеш. Код для этого был бы вполне поддающимся генерации из метаданных кеша, но это нужно было бы сделать во время компиляции. Возможно, вы сможете что-то сделать с помощью шаблонов или переопределить оператор ->
, чтобы сделать протокол доступа более прозрачным, но это, вероятно, больше проблем, чем того стоит.
Спасибо за обширный ответ. Не могли бы вы добавить примерный код или ссылку на некоторые примеры из общедоступного домена? – 2010-02-10 13:50:18