![]() |
| ||
|
|
Новости |
Поиск |
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);
Опять работает Что не так?
(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]
> Не считается за попытку?
Попытка, не приведшая к успеху, за попытку не считается.