Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Придумал архетиктуру с пакетами и медиатором, помогите реализоват


Страницы:   1 2

Kolan ©   (2007-07-03 18:12:00) 

ь
:)

Здравствуйте,
 Придумал и почти реализовал такую архитектуру:

Есть медиатор в пакете(KMediator.bpl):
TSystemMediator = class
 strict private
   FColleagues: TList;
   class var FInstance: TSystemMediator;
   constructor Create;
 public
   class function GetInstance: TSystemMediator;
   class procedure DestroyInstance;
   class function IsInstanceAssigned: Boolean;
   destructor Destroy; override;
    procedure SendMessage(Command: TCustomCommand);
   procedure Attach(Colleague: TCustomColleague);
   procedure Detach(Colleague: TCustomColleague);
 end;

 TCustomColleague = class abstract
 strict private
 public
   constructor Create;
   destructor Destroy; override;
    procedure ExecuteCommand(Command: TCustomCommand); virtual; abstract;
 end;


То есть он делает броад каст всем коллегам.

В том же пакете есть комманда:
 TCustomCommand = class
 strict private
   FAutoDestroy: Boolean;
 public
   constructor Create;
   function This: TCustomCommand;
   property AutoDestroy: Boolean read FAutoDestroy write FAutoDestroy;
 end;


Главная форма такого приложения загружает пакет с загрузчиком медиатора  и коллег. KColleaguesLoader.bpl


Вот пример пакета коллеги:

unit KTestColleagueAddresseeUnit;

interface
uses
 Dialogs, KSystemMediator, KCustomCommand;
type
 TTestColleagueAddressee = class(TCustomColleague)
 public
   procedure ExecuteCommand(Command: TCustomCommand); override;
 end;
var
 TestColleagueAddressee: TTestColleagueAddressee;
implementation

{ TTestColleague }

procedure TTestColleagueAddressee.ExecuteCommand(Command: TCustomCommand);
begin
 inherited;
 if Command is TCustomCommand then
   ShowMessage('Colleague test ok.');
end;

initialization
 TestColleagueAddressee := TTestColleagueAddressee.Create;
finalization
 TestColleagueAddressee.Free;

end.


Итак это работает так:
1. Загружается гл. форма.
2. В свойм конструкторе форма загружает пакет KColleaguesLoader.bpl
3. Загрузившись загрузчик в пакете KColleaguesLoader.bplзагружает пакет с медиатором KMediator.bpl
4. Загрузчик сканирует директорию и загружет всех коллег.
5. Коллеги при загрузке присоединяются к медиатору.

Все это работает.

Теперь вопрос.
Я хочу сделать коллегу в главной форме.
Для этого я
1. в Project-Options-Packages дабавляю пакет с медиатором.
Запускаю, проверяю — работает
2. В uses гл. формы добавляю модули KCustomCommand, KSystemMediator.
Запускаю, проверяю — работает
3. Кидаю кнопку, в ней(в OnClick) пишу:
TSystemMediator.GetInstance.SendMessage(TCustomCommand.Create);

Запускаю — AV на
begin
 Application.Initialize;
 Application.CreateForm(TCustomColleagueMainForm, CustomColleagueMainForm);
 Application.Run;
end.


Комментирую
TSystemMediator.GetInstance.SendMessage(TCustomCommand.Create);

Опять работает — Что не так?


Kolan   (2007-07-04 10:46:00) [21]

> Теперь компилится нормально.

Я кстати не понял почему стало компилироваться, вчем смысл был?


Kolan   (2007-07-04 10:46:00) [22]

Ой, блин

[5] SlymRO ©   (04.07.07 05:10)
1. в Project-Options-Packages дабавляю пакет с загрузчиком медиатора.

Помогло, просто я случайно пакет с загрузчиком медиатора добавил, а сам медиатор не стёр.

Теперь компилится нормально.

НО! Видимо создаётся еще один медиатор, тк
TSystemMediator.GetInstance.SendMessage(TCustomCommand.Create);
Ни к чему не приводит. Коллеги не получают это сообщение.

А если посылать сообще ние из одного из коллего, то получают.


Kolan   (2007-07-04 10:41:00) [23]

Игорь Шевченко посоветует взять в руки отладчик и решить проблему самостоятельно.

А что :
[7] Kolan ©   (04.07.07 08:55)
Не считается за попытку?


Игорь Шевченко   (2007-07-04 10:39:00) [24]


> Оч. жду Игоря Шевченко, который сказал, что это нормальное
> решение + использует пакеты в хвост и гриву :).


Игорь Шевченко посоветует взять в руки отладчик и решить проблему самостоятельно.


Kolan   (2007-07-04 10:37:00) [25]

Не то чтобы мне не с кем поговорить…

Просто я продумал система и на основе этого каркаса все оч. хорошо получается, только эта проблемма держит, может, извените за наглость, я проект(328кБ) комк-нить скину, а?


Kolan   (2007-07-04 10:02:00) [26]

Может это потому, что коллеги и медиатор лежат не в папке с гл. формаой и соотв exe, а в .\Plugins\
А?


Kolan   (2007-07-04 09:01:00) [27]

Главное когда в Requires пакетов добавляю медиатор, то нормально. А когда в Build with run time packegesоблом. В чем разница?


Kolan   (2007-07-04 08:55:00) [28]

Поставил точки вов сех пакетах системы где есть initialization. И запускался из каждого(с пом. Host application).
Везде ошибка Project raised too many consecutive exceptions.

А при запуске из медиатора происходит все так:

Попадаем в консруктор формы:
procedure TCustomColleagueMainForm.FormCreate(Sender: TObject);
begin
 LoadColleaguesLoader;
end;


Вот код этой процедуры:
procedure LoadColleaguesLoader;
begin
 if FileExists(GetRootDir + rsColleagueLoader) then
   LoadPackage(GetRootDir + rsColleagueLoader)
 else
   raise Exception.Create(Format(rsNoColleagueLoaderException, [rsColleagueLoader]));
end;


После LoadPackageкак и положено попадаем в инициализацию загрузчика коллег
initialization
 PluginLoader := TPluginLoader.Create;
 PluginLoader.LoadPlugins;
finalization
 PluginLoader.Free;


Он создаётся нормально и переходит к загрузке LoadPlugins

function TPluginLoader.LoadPlugins: Boolean;
var
 Strings: TStrings;
 I: Integer;
 MediatorHandle: THandle;
begin
 Result := False;
 MediatorHandle := LoadMediator;
 if MediatorHandle 0 then
 begin
   FPluginsHandles.Add(MediatorHandle);
   Result := True;

   {All other colleagues load.}
   Strings := TStringList.Create;
   ScanDirectory(GetRootDir+rsPluginsDir, True, Strings, rsPluginExtension,
     '', 0);
   for I := 0 to Strings.Count — 1 do
   begin
     if ExtractFileName(Strings[I]) rsMediatorName then
       LoadPackage(Strings[I]);
   end;
   Strings.Free;
 end;
end;


Нормально загружает медиатор и всех коллег — проверил отладкой.

Ставлю точку на последний endв LoadPlugins. Жму F7 и получаю
Exception: Не могу загрузить пакет KMediator, так как он содержит модуль KCustomCommand, который содержит KMediator.

То есть видимо форма еще раз загружает(пытается) медиатор. Как от этого уйти. Медиатор — это же синглетон он нужен 1.

Каккие пути решения?


Kolan   (2007-07-04 08:14:00) [29]

> команды колега может разослать доп команду… все приехали
> Stack overflow…

Часто бывает. Проблем небыло. Правда без пакетов.


> Предлагаю использовать способ подписки на команды…

Подумать надо.

Я решил проблему(частично) используюя предков для разных типов комманд. Поэтому коллеги проверяют не каждую комманду, а вначале проверяют из той ли она группы вообще…

НО! Это не суть вопроса.
в Project-Options-Packages дабавляю пакет с загрузчиком медиатора.
Почти та же реакция, только ошибка — Project raised too many consecutive exceptions.
Кстати я не понял. Я убралпакет с медиатором и подключил пакет с загрузчиком. Почему в uses он не ругается на  KSystemMediator, KCustomCommand он же теперь по идее ничего про них незнает…

Мне кажется что написание или не написание строки:
TSystemMediator.GetInstance.SendMessage(TCustomCommand.Create);

Приводит к тому что если её нет компилятьр опртимизирует и хоть KSystemMediator, KCustomCommand есть в uses он их не включает.

А если она есть он их включает и — ошибка…

Что делать? Как же решить? Может я мало кода привел? Куда копоть?


SlymRO   (2007-07-04 05:10:00) [30]

1. в Project-Options-Packages дабавляю пакет с загрузчиком медиатора.
По архитектуре: все правильно, но... броад каст всемэто черезчур... если Colleagов мало... все гуд... а если много и при обработке команды колега может разослать доп команду... все приехали Stack overflow...
можно добавить в SendMessage Initiator:TSomeClass- чтобы сам на себя не зациклился...
Предлагаю использовать способ подписки на команды...
или древовидную систему обработки сообщений...
System(TSystemMediator)
->FileOp(TFamilyMediator)
-->TCustomColleague
->WndOp(TFamilyMediator)
-->TCustomColleague
SystemMediator загружает TFamilyMediatorы, они в свою очередь регистрируют тип семейства сообщений и его символический идентификатор... и отзываются только на свой тип сообщения... загружает колег своего типа...


Kolan   (2007-07-04 00:54:00) [31]


> Ставь точки останова и смотри.

Запустил(указал host application) пакет с медиатором:
Получил сообщение: Не могу загрузить пакет KMediator, так как он содержит модуль KCustomCommand, который содержит KMediator.

Моё имхо, что тут виноват не мой код, а то как загружаются пакеты видимо медиатор загружается дважды…
Как исправить?


Kolan   (2007-07-04 00:47:00) [32]

> Кстати сам проект и все пакеты собраны с галкой «build
> with runtime packages»? я  не увидел в описании этого момента

Да. См[0]:
1. в Project-Options-Packages дабавляю пакет с медиатором.


Sergey Masloff   (2007-07-03 22:18:00) [33]

Ну если AV на бегине то всяко дело в какой-то секции инициализации. Ставь точки останова и смотри.
 Кстати сам проект и все пакеты собраны с галкой "build with runtime packages"? я  не увидел в описании этого момента


Kolan   (2007-07-03 18:33:00) [34]

Оч. жду Игоря Шевченко, который сказал, что это нормальное решение + использует пакеты в хвост и гриву :).


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо