Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.10.07;
Скачать: [xml.tar.bz2];

Вниз

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

 
Kolan ©   (2007-07-03 18:12) [0]

ь
:)

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

Есть медиатор в пакете(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-03 18:33) [1]

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


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

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


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

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

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


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


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

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

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


 
SlymRO ©   (2007-07-04 05:10) [5]

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


 
Kolan ©   (2007-07-04 08:14) [6]

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

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


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

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

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

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

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

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

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

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


 
Kolan ©   (2007-07-04 08:55) [7]

Поставил точки вов сех пакетах системы где есть 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 &#151; 1 do
   begin
     if ExtractFileName(Strings[I]) <> rsMediatorName then
       LoadPackage(Strings[I]);
   end;
   Strings.Free;
 end;
end;


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

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

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

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


 
Kolan ©   (2007-07-04 09:01) [8]

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


 
Kolan ©   (2007-07-04 10:02) [9]

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


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

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

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


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


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


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


 
Kolan ©   (2007-07-04 10:41) [12]

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

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


 
Kolan ©   (2007-07-04 10:46) [13]

Ой, блин

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

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

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

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

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


 
Kolan ©   (2007-07-04 10:46) [14]

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

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


 
Игорь Шевченко ©   (2007-07-04 11:08) [15]

Kolan ©   (04.07.07 10:41) [12]


> Не считается за попытку?


Попытка, не приведшая к успеху, за попытку не считается.


 
Игорь Шевченко ©   (2007-07-04 11:12) [16]

А может того, рановато с медиаторами ? Может матчасть подучить слегка ?


 
DrPass ©   (2007-07-04 11:30) [17]


>  Кстати сам проект и все пакеты собраны с галкой "build
> with runtime packages"?

Это надо еще постараться собрать пакеты со статической компоновкой :)


 
Kolan ©   (2007-07-04 12:11) [18]

> А может того, рановато с медиаторами ? Может матчасть подучить
> слегка ?

Может и рановато&#133 Но надо сделать.

А мат часть в части пакетов учить или где?


 
Игорь Шевченко ©   (2007-07-04 12:12) [19]


> А мат часть в части пакетов учить или где?


В части ответов на вопросы почему не компилировалось, например.


> Может и рановато… Но надо сделать.


А что, нельзя сделать проще ? :)


 
Kolan ©   (2007-07-04 18:32) [20]

> В части ответов на вопросы почему не компилировалось, например.

Ну я правда не доконца понял. :(

А что, нельзя сделать проще ? :)
Можно, но потом будет оч. сложно&#133

Так что это и есть(имхо) проще всего.

Тем более что каркас такой я апробовал(успешно) на реальном проекте. Еслибы не он, то имхо я бы по срокам не успел&#133 Правда я не использовал пакеты&#133


 
Kolan ©   (2007-07-04 18:53) [21]

> В части ответов на вопросы почему не компилировалось, например.

Ладно уточню про мат часть.
Если я еще раз прочту главу про пакеты Тейкста и Пачеко, я всмогу оттуда получить ответ на вопрос почему же не компилилось?

ЗЫ
Глупый действительно вопрос &laquo;Почему не компилилось?&raquo;, он-то компилилось, просто сразу при старте вываливалось с ошибкой.

Итого:
 Если я еще раз прочту главу про пакеты Тейкста и Пачеко, я всмогу оттуда получить ответ на вопрос, почему же сразу вываливалось с ошибкой?.
И почему я получал Не могу загрузить пакет KMediator, так как он содержит модуль KCustomCommand, который содержит KMediator.
И почему теперь, по всей видимости, загружается два экземпляра пакета с медиатором?

Смогу?


 
SlymRO ©   (2007-07-05 08:56) [22]

1. build with: KMediator,KColleaguesLoader
KColleaguesLoader requires KMediator
если нет requires то KSystemMediator, KCustomCommand будут скомпилированы дважды, 1 раз в KMediator, 2 раз в KColleaguesLoader.
Не проже лоадер совместить с медиатором в одном пакете?

2. какой LoadPackage(GetRootDir + rsColleagueLoader)? если ты статично их прилинковываешь "build with" KColleaguesLoader


 
Kolan ©   (2007-07-05 16:04) [23]


> SlymRO ©   (05.07.07 08:56)

Тааак,
1. Да у KColleaguesLoader  нет медиатора в requires. Шас включю и проверю.

2. Ну раньше же я вообще ничего не подключал к форме. поэтому и LoadPackage. Тут не понял. Что надо сделать? Не делать вообще LoadPackage, да?


 
Kolan ©   (2007-07-05 16:13) [24]

Короче добавил в KColleaguesLoader в requires KMediator.
А в форме в кострукторе закоментил:

procedure TCustomColleagueMainForm.FormCreate(Sender: TObject);
begin
 //LoadColleaguesLoader;
end;


Программа запускается, но останалвилается на begin

begin
 Application.Initialize;
 Application.CreateForm(TCustomColleagueMainForm, CustomColleagueMainForm);
 Application.Run;

end.


Жму F9, появляется форма в Evant log начинают сыпатся сообщения. Что то вроде бесконечного цикла что-ли&#133

ЗЫ
 Мож я таки закину прект, а? Явно ведь с создание пакетов что-то&#133 :(

2 раз в KColleaguesLoader
Почему их нет же в uses. Вот всё целиком:


unit KColleaguesLoaderUnit;

interface
uses
 SysUtils, Classes, Dialogs;
resourcestring
 rsPluginsDir = "Plugins";
 rsPluginExtension = ".bpl";
 rsMediatorName = "KMediator.bpl";

 rsDirectoryDoesNotExists = "Указаная папка не существует.";
 rsMediatorNotFound = "Медиатор не найден.";
type
 EPluginLoaderException = class(Exception);

 THandleList = class(TList)
 private
   function GetItem(Index: Integer): THandle;
   procedure SetItem(Index: Integer; const Value: THandle);
 public
   function Add(Handle: THandle): Integer;
   property Items[Index: Integer]: THandle read GetItem write SetItem; default;
 end;

 TPluginLoader = class
 strict private
   FPluginsHandles: THandleList;
 strict protected
   function GetRootDir: string;
   function LoadMediator: THandle;
   procedure ScanDirectory(Directory: string; ScanSubFolders: Boolean;
     Strings: TStrings; Extension: string; FileName: string; RecursionCount: Integer);
 public
   function LoadPlugins: Boolean;
   constructor Create;
   destructor Destroy; override;  
 end;
var
 PluginLoader: TPluginLoader;
implementation

{ THandleList }

function THandleList.Add(Handle: THandle): Integer;
begin
 Result := inherited Add(Pointer(Handle));
end;

function THandleList.GetItem(Index: Integer): THandle;
begin
 Result := THandle(inherited Items[Index]);
end;

procedure THandleList.SetItem(Index: Integer; const Value: THandle);
begin
 inherited Items[Index] := Pointer(Value);
end;

{ TPluginLoader }

constructor TPluginLoader.Create;
begin

 FPluginsHandles := THandleList.Create;
end;

destructor TPluginLoader.Destroy;
var
 I: Integer;
begin
 for I := 0 to FPluginsHandles.Count &#151; 1 do
   UnloadPackage(FPluginsHandles[I]);
 FPluginsHandles.Free;
 inherited;
end;

function TPluginLoader.GetRootDir: string;
begin
 Result := IncludeTrailingPathDelimiter(ExtractFileDir(ParamStr(0)));
end;

function TPluginLoader.LoadMediator: THandle;
var
 Strings: TStrings;
begin
 Result := 0;
 Strings := TStringList.Create;
 ScanDirectory(GetRootDir, False, Strings, rsPluginExtension,
   rsMediatorName, 0);
 if Strings.Count > 0 then
   Result := LoadPackage(Strings[0]);
 Strings.Free;
end;

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 &#151; 1 do
   begin
     if ExtractFileName(Strings[I]) <> rsMediatorName then
       LoadPackage(Strings[I]);
   end;
   Strings.Free;
 end;
end;

procedure TPluginLoader.ScanDirectory(Directory: string;
 ScanSubFolders: Boolean; Strings: TStrings; Extension: string;
 FileName: string; RecursionCount: Integer);
var
 CurrentFile: TSearchRec;
begin
 Directory := IncludeTrailingPathDelimiter(Directory);
 if Assigned(Strings) and DirectoryExists(Directory) then
 begin
   try
     if FindFirst(Directory + "*.*", faAnyFile, CurrentFile) = 0 then
     begin
       repeat
         if (CurrentFile.Name <> ".") and (CurrentFile.Name <> "&#133") then
         begin
           if ((CurrentFile.Attr and faDirectory) <> 0) and ScanSubFolders then
             ScanDirectory(Directory+CurrentFile.Name, ScanSubFolders, Strings,
               Extension, FileName, RecursionCount + 1);
            if (Extension = "") or (ExtractFileExt(CurrentFile.Name) = Extension) then
              if (FileName = "") or (FileName = CurrentFile.Name) then
               Strings.Add(Directory+CurrentFile.Name)
         end;
       until FindNext(CurrentFile) <> 0;
     end;
   finally
     FindClose(CurrentFile);
   end;
 end;
end;

initialization
 PluginLoader := TPluginLoader.Create;
 PluginLoader.LoadPlugins;
finalization
 PluginLoader.Free;

end.


 
Kolan ©   (2007-07-05 16:25) [25]

Ставил точку до сюда:
initialization
 PluginLoader := TPluginLoader.Create;
 PluginLoader.LoadPlugins;
finalization
 PluginLoader.Free;


Дело не доходит &#151; :(.


 
SlymRO ©   (2007-07-06 05:53) [26]

Удалено модератором


 
Kolan ©   (2007-07-06 08:31) [27]

Удалено модератором


 
Kolan ©   (2007-07-06 09:01) [28]

Короче я ничего не понял.

Уточняю вопрос. Что я хочу:

1. Есть проект с формой. У ничего не отмечена галка Build with run time packages. То есть просто проект.
2. Этот проект загружает загрузчик коллег. LoadPackage
3. Загрузчик коллег загружает медиатор и всех коллег. LoadPackage
4. Коллеги &#151; пакеты. В requires у них медиатор.bpl и ни могут послать и принимать комманды.

Что конкретно мне нужно:
Послать комманду из формы проекта(1). Что конкретно для этого нужно сделать? По шагам?


 
Kolan ©   (2007-07-06 10:23) [29]

Добавил лог:

procedure TSystemMediator.Attach(Colleague: TCustomColleague);
begin
 FColleagues.Add(Pointer(Colleague));
 LogManager.WriteString("Attach: "+Colleague.ClassName);
end;

constructor TSystemMediator.Create;
begin
 FColleagues := TList.Create;
 LogManager.WriteString("Creatinon: "+Self.ClassName);
end;

Файл лога создаётся так:
Randomize;                                  
 S := ExtractFilePath(Application.ExeName) + Application.Title +IntToStr(Random(10))+ "Log.log";


Тест 1.
В гл форме нет Build with run time packages.
В загрузчите коллег нет медиатора в reauires

Получается два файла!
Один пустой. Второй:
1 10:16:30:703 Creatinon: TSystemMediator
2 10:16:30:703 Attach: TTestColleagueAddressee


Откуда пустой файл?

Тест 2.
Добавил медиактор в reauires в пакет с загрузчиком
Результат тот же.

Все еще ничего не понимаю :( Откуда берётся этот файл пустой. И как сделать :(
Тест 3.
Добавил загрузчик пакетов Build with run time packages
Результат &#151; AV, фйлы не зоздались.

Тест 4.
Вместо загрузчика добавил медиатор в Build with run time packages
Результат &#151; AV, фйлы не зоздались.


 
Kolan ©   (2007-07-06 11:04) [30]

Млииин может ошибка в том, что медиатор я клал в папку с плагинами, а не с гл. формой&#133


 
Kolan ©   (2007-07-06 11:06) [31]

Ппц,

убрал из загрузчика загрузку медиатора.
В проект с формой добавил KMediator;KColleaguesLoader.

Ура, работает! И файл с логом только 1. Вроде всё.

Благодарю SlymRO, ты видимо именно это и советовал. :)


 
Игорь Шевченко ©   (2007-07-06 11:17) [32]


> 1. Есть проект с формой. У ничего не отмечена галка Build
> with run time packages. То есть просто проект.
> 2. Этот проект загружает загрузчик коллег. LoadPackage


Так не надо делать.


 
Kolan ©   (2007-07-06 11:39) [33]

> [32] Игорь Шевченко ©   (06.07.07 11:17)
> Так не надо делать.

А как в [31]? &#151; Вроде всё рабоате.
Еще раз в итоге так:
1. В проекте с гл. формой в Build with run time packages KMediator;KColleaguesLoader. Оба эти пакета в папке с *.exe.

2. При создании загрузчик коллег загружает только их.


 
имя   (2007-07-29 00:22) [34]

Удалено модератором



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2007.10.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.06 c
2-1189331798
zzz0001
2007-09-09 13:56
2007.10.07
В ЧЕМ ОШИБКА???


1-1185116122
Al_delta
2007-07-22 18:55
2007.10.07
TreeView: неправильно создаются дочерние узлы. Помогите!


15-1189495429
BOA_KAA
2007-09-11 11:23
2007.10.07
Как сделать это быстрее?


15-1189531719
TStas
2007-09-11 21:28
2007.10.07
Как же бороться с брандмауэром?


2-1189580698
artem779
2007-09-12 11:04
2007.10.07
область видимости





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский