![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Придумал архетиктуру с пакетами и медиатором, помогите реализоват
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]Оч. жду Игоря Шевченко, который сказал, что это нормальное решение + использует пакеты в хвост и гриву :).