![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача методу COM-сервера объекта(TClientDataSet) в параметре
Robin © (2002-07-31 12:19:00)Помогите в следующем:
Есть COM-объект (Automation Object).
В методе COM-объекта создаю форму и показываю ее.
На форме лежит DBGrid, DataSource и ClientDataSet.
В вызывающей программе есть связка:
DataBase, Query, Provider и ClientdataSet.
Вопрос: как связать ClientDataSet вызывающей программы с ClientDataSetом
из COM-объекта, чтобы в нем на форме в DBGridе получил данные
от вызывающей программы.
P.s. : при реализации выше описанного через DLL результат получал через
передачу ClientDataSeta в параметре функции DLL.
Romkin (2002-08-14 22:32:00) [1]Насколько понял, нужен просто MIDAS server в dll, так будет проще всего. Я вижу два варианта
1. Создать ActiveX library а в ней RemoteDataModule, а подключиться действительно можно через TDCOMConnection - что мешает? Просто не указывать имя хоста, и будет подгрузка
2. Тоже самое, но для подключения вызывать CreateOleObject/CreateCOMObject и др., с прямым преобразованием к IAppServer (Delphi 5?), и вручную работать с данными через методы этого интерфейса
3. Реализовать собственный T...Connection по аналогии с TDCOMConnection, это просто, там буквально два или три метода
2 А. Н. Оним а то, что если используешь COM, то передавать только интерфейсы - поддерживаю полностью
Robin (2002-08-01 15:21:00) [2]2 А. Н. Оним (31.07.02 18:19)
Спасибо за разъяснения.
Немножко тут продвинулся передавая в COM не ClientDataSet, а
ClientDataSet.Data. Но в COM-объекте тогда получается "подвисший" ClientDataSet, т.е. без Providerа.
2 DiamondShark © (31.07.02 18:10)
Но чего то не догоняю: ведь TRemoteDatamodule - тоже COM-объект.
То есть приходим к DCOMConnection. Или я не прав?
Можно пожалуйста поподробнее.
А. Н. Оним (2002-07-31 18:19:00) [3]Полагаю, что DiamondShark прав и есть более простые решения этой проблемы (но сам я, признаться, подолгу не работал ни с DataSet'ами, ни с RemoteDataModul'ями) и COM кажется притянутым здесь за уши.
Назначение IPersonal очень простое. Передать экземпляру CoClass ссылку на DataSet. Это можно сделать тысячью способов и обойтись без этого COM-интерфейса, но у меня просто правило такое - доступ к СOM объекту (даже внутри его сервера) только через его COM интерфейсы. Не нравится - не надо.
DiamondShark (2002-07-31 18:10:00) [4]А что, TRemoteDatamodule, TDatasetProvider уже отменили?
Robin (2002-07-31 17:56:00) [5]А. Н. Оним (31.07.02 17:16) >
Спасибо за мысль.
Пойду вчитаюсь во II-й том Стива Тейксера.
Бо пока не очень все понятно: как реализовать
IDataSet (т.е. в моем случае IClientDataSet) и в чем идея IPersonal?
Если можно, немножко разъясните.
Robin (2002-07-31 17:41:00) [6]А. Н. Оним >
Задача то простая:
Есть несколько программ, которые используют одни и те же формы (Справочник клиентов и др.),которые в свою очередь отображают
информацию одного или нескольких наборов данных.
Если форма меняется, то приходится перекомпилировать все проекты, использующие форму (:
Эту беду попробовал решить через DLL - вроде ничего.
Но в итоге решил сделать через COM.
Сценарий определил такой:
1.) Есть сервер приложений (MIDAS), в котором живут
компоненты доступа к БД ORACLE через ODAC (OraSession,
OraQuery, OraProvider);
2.) Есть клиентские приложения, обращающиеся к серверу
приложений через DCOM. В этих приложениях живут
TClientDataSetы.
3.) Есть набор форм, используемые клиентскими приложениями.
Эти формы то и отображают информацию из наборов данных,
получаемую от клиентских приложений.
Связь [IN, OUT] с ClientDataSetом нужна, чтобы сообщить
клиентскому приложению об изменениях набора данных,
произведенных в форме COM-объекта.
Пункты 1.) и 2.) реализовал, а 3.) - в печали и тумане.
Кидать в каждую форму COM-объекта компонент DCOMConnection
не хотелось бы (:
Еж ли что не так нагородил,
то буду очень благодарен за разъяснения.
А. Н. Оним (2002-07-31 17:16:00) [7]Можно попробовать так:
1. --Клиент--
Клиент содержит COM объект-обёртку, что реализует пару интерфейсов. Например, IDataSet и IPersonal.
* IDataSet содержит примерно те же методы, что и TDataSet
* IPersonal позволяет назначить объекту управляемый им DataSet.
Клиент создаёт экземпляр такого кокласса, и через IPersonal передаёт ему экземпляр DataSet'а. Так как и DataSet и COM объект в одном процессе (InProc) - это пройдёт. Предполагается, что клиентский COM объект реализует IDataSet перенаправлением вызовов метода этого интерефейса на назначенный ему через IPersonal экземпляр DataSet.
2. --Сервер--
Сервер выставляет ConnectionPoint, позволяющий принимать такие обёртки.
3. --Клиент--
Клиент посылает серверу такую обёртку (например, через IConnectionPoint сервера).
4. --Сервер--
На Сервер есть класс, который является наследником DataSet, но перенаправляет вся вызовы своих методов (делегирует вызовы) на объект обёртку, а ещё конкретней на его интерфейс IDataSet, полученный от клиента.
В этой схеме клиент может менять данные в своём реальном DataSet'е, а сервер, обладающий прокси обёртки клиента, дёргает через проксие клиентский объект, тот, в свою очередь, дёргает назначенный ему DataSet, а уже тот и выполняет все операции. По идее, всё должно работать.
А. Н. Оним (2002-07-31 16:55:00) [8]В DLL да ещё и на одной машине такие фокусы как передача экземпляров класса всегда будет проходить, так как и сервер и клиент живут в одном адрессном пространстве и всё что нужно сделать, так это обратиться к одному участку памяти. Правда я не гарантирую, что это будет работать, если клиент и сервер будут скомплированы на разных версиях Delphi. Но пока это прекрасно получается и переданная тобой ссылка на экземпляр класса DataSet (как указатель на область памяти) будет иметь смысл для сервера.
Как только клиент и сервер живут в разных адрессных пространствах - всё летит кувырком и указатель на область памяти клиента для сервера теряет всякий смысл. DataSet не является COM объектом, поэтому его передача в вызове метода не приведёт к процессу маршлалинга (создания прокси клиентского экземпляра кокласса на сервере) и его передача как в случае InProc взаимодействия невозможна.
Не очень всё-таки понимаю, что за задача решается, но могу предложить следующий общий подход: реализовать в серверном коклассе методы обмена информацией между клиентом и сервером. Когда на клиенте происходят изменения, то клиент посылает обновлённые значения на сервер и наоборот, сервер посылает изменённые значения в качестве CallBack'ов клиенту через клиентский Sink объект. Для Callback'ов Посмотри интерфейсы IConnectionPointContainer, IConnectionPoint. Если ты пишешь в Delphi, то вопрос обратных вызовов рассматривается, например, во II томе Стива Тейксера (Delphi 5 руководство разработчика) со страницы 245.
Нельзя ли поподробней рассказать о решаемой задаче?