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);

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


  (2007-07-29 00:22:00) [1]

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


Kolan   (2007-07-06 11:39:00) [2]

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

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

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


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


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


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


Kolan   (2007-07-06 11:06:00) [4]

Ппц,

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

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

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


Kolan   (2007-07-06 11:04:00) [5]

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


Kolan   (2007-07-06 10:23:00) [6]

Добавил лог:

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
Результат — AV, фйлы не зоздались.

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


Kolan   (2007-07-06 09:01:00) [7]

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

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

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

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


Kolan   (2007-07-06 08:31:00) [8]

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


SlymRO   (2007-07-06 05:53:00) [9]

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


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

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


Дело не доходит — :(.


Kolan   (2007-07-05 16:13:00) [11]

Короче добавил в 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 начинают сыпатся сообщения. Что то вроде бесконечного цикла что-ли…

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

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 — 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 — 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 '…') 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:04:00) [12]


> SlymRO ©   (05.07.07 08:56)

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

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


SlymRO   (2007-07-05 08:56:00) [13]

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-04 18:53:00) [14]

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

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

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

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

Смогу?


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

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

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

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

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

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


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


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


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


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


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


Kolan   (2007-07-04 12:11:00) [17]

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

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

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


DrPass   (2007-07-04 11:30:00) [18]


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

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


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

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


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

Kolan ©   (04.07.07 10:41) [12]


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


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


Страницы:   1 2

Наверх

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