Асинхронное событие через универсальный интерфейс

Мне нужно подключить несколько измерительных устройств к моему приложению (например, штангенциркуль, весовая шкала, ...), не привязываясь к конкретной марке или модели, поэтому на стороне клиента я использую интерфейсы с общими методами (QueryValue). Устройства подключены к COM-порту и доступны асинхронно:

  1. Запросить значение (= отправить определенную последовательность символов на COM-порт)
  2. Ждать ответа

На бизнес-стороне мои компоненты используют 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;
Другие вопросы по тегам