Я хочу создать класс-потомок TService
, который я использую в качестве основы для моих Windows реализаций службы. В моем базовом классе я представляю опубликованное свойство ServiceDescription
и использую обработчик событий AfterInstall
, чтобы записать это описание в соответствующее место в реестре Windows.
Обратите внимание, что, поскольку * Класс 1006 * (объявленный в Vcl.SvcMgr
) является потомком TDataModule
, для того чтобы свойство ServiceDescription
было видно в Инспекторе объектов, необходимо объявить этот базовый класс в пакете designtime и зарегистрировать его с помощью Delphi используя звонок на RegisterCustomModule
. Кроме того, потомок этого базового класса должен генерироваться мастером OTA (open tools api) или генератором кода (файлы .pas и .dfm). Нет проблем, у меня есть что-то отсортированное, и если вам интересно, вы можете прочитать об этом больше из книги Марко Канту (http://www.marcocantu.com/ddh/ddh15/ddh15e.htm).
Где я застрял я хочу использовать обработчик событий AfterInstall
в своем базовом классе для записи в реестр и AfterUninstall
для его удаления, но я хочу убедиться, что мои классы-потомки также будут поддерживать AfterInstall
и AfterUninstall
events.
Ранее я узнал от Рэя Конопки, что если вы хотите снова ввести свойство, вы должны использовать методы доступа в классе-потомке. В результате вот фрагмент кода, который представляет мою попытку сделать это в отношении события AfterInstall
:
private
// field to store method pointer for the descendant AfterInstall event handler
FFAfterInstall: TServiceEvent;
…
protected
function GetAfterInstall: TServiceEvent;
procedure SetAfterInstall( value: TServiceEvent );
…
published
property AfterInstall: TServiceEvent read GetAfterInstall write SetAfterInstall;
Мой переопределенный конструктор назначает метод унаследованному свойству AfterInstall
:
constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
Self.AfterInstall := CallAfterInstall;
…
end;
В моей реализации CallAfterInstall
после запуска кода для записи в реестр Windows я проверяю, был ли указатель метода назначен моему полю указателя локального метода, и если да, то Я это называю Это выглядит примерно так:
procedure TTPMBaseService.CallAfterInstall(Service: TService);
var
Reg: TRegistry;
begin
// Code here to write to the Windows Registry is omitted
// Test if our method pointer field has been written to
if Assigned( FFAfterInstall ) then
FFAfterInstall( Service ); // call the method,
…
end;
Я думаю, что все это имеет большой смысл, и я думаю, что это должно работать. Тем не менее, я застрял на методы доступа. Метод доступа Get компилируется просто отлично, и вот он:
function TTPMBaseService.GetAfterInstall: TServiceEvent;
begin
Result := FFAfterInstall;
end;
Но мой метод SetAfterInstall
вызывает исключение времени компиляции, сообщая, что не хватает параметров:
procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent );
begin
if value <> FFAfterInstall then
FFAfterInstall := value;
end;
Я не уверен, что здесь делать. Я сделал следующее изменение, и оно компилируется, но, похоже, не выполняет эту работу:
procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent);
begin
if @value <> @FFAfterInstall then
@FFAfterInstall := @value;
end;
У меня два вопроса. Во-первых, правильно ли я отношусь к повторному представлению обработчика событий, при этом гарантируя, что и мой базовый класс, и его потомки поддерживают это событие? Если мой лог c правильный, что я делаю не так с методом доступа Setter?