Асинхронное событие через универсальный интерфейс
Мне нужно подключить несколько измерительных устройств к моему приложению (например, штангенциркуль, весовая шкала, ...), не привязываясь к конкретной марке или модели, поэтому на стороне клиента я использую интерфейсы с общими методами (QueryValue
). Устройства подключены к COM-порту и доступны асинхронно:
- Запросить значение (= отправить определенную последовательность символов на COM-порт)
- Ждать ответа
На бизнес-стороне мои компоненты используют TComPort для внутреннего использования, что является событием приема данных. TComPort.OnRxChar
, Интересно, как я мог запустить это событие через интерфейс? Вот что я сделал до сих пор:
IDevice = interface
procedure QueryValue;
function GetValue: Double;
end;
TDevice = class(TInterfacedObject, IDevice)
private
FComPort: TComPort;
FValue: Double;
protected
procedure ComPortRxChar;
public
constructor Create;
procedure QueryValue;
function GetValue: Double;
end;
constructor TDevice.Create;
begin
FComPort := TComPort.Create;
FComPort.OnRxChar := ComPortRxChar;
end;
// COM port receiving data
procedure TDevice.ComPortRxChar;
begin
FValue := ...
end;
procedure TDevice.GetValue;
begin
Result := FValue;
end;
Но мне нужно событие, чтобы знать, когда позвонить GetValue
на стороне клиента. Какой обычный способ выполнить такой поток данных?
1 ответ
Вы можете добавить свойство события в интерфейс
IDevice = interface
function GetValue: Double;
procedure SetMyEvent(const Value: TNotifyEvent);
function GetMyEvent: TNotifyEvent;
property MyEvent: TNotifyEvent read GetMyEvent write SetMyEvent;
end;
и реализовать это в классе TDevice
TDevice = class(TInterfacedObject, IDevice)
private
FMyEvent: TNotifyEvent;
procedure SetMyEvent(const Value: TNotifyEvent);
function GetMyEvent: TNotifyEvent;
public
function GetValue: Double;
procedure EmulChar;
end;
Тогда как обычно называют FMyEvent
обработчик (если назначен) в конце ComPortRxChar
,
Tform1...
procedure EventHandler(Sender: TObject);
procedure TForm1.EventHandler(Sender: TObject);
var
d: Integer;
i: IDevice;
begin
i := TDevice(Sender) as IDevice;
d := Round(i.GetValue);
ShowMessage(Format('The answer is %d...', [d]));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
id: IDevice;
begin
id:= TDevice.Create;
id.MyEvent := EventHandler;
(id as TDevice).EmulChar; //emulate rxchar arrival
end;
procedure TDevice.EmulChar;
begin
if Assigned(FMyEvent) then
FMyEvent(Self);
end;
function TDevice.GetMyEvent: TNotifyEvent;
begin
Result := FMyEvent;
end;
function TDevice.GetValue: Double;
begin
Result := 42;
end;
procedure TDevice.SetMyEvent(const Value: TNotifyEvent);
begin
FMyEvent := Value;
end;