Delphi 通过通用接口的异步事件
我必须将多个测量设备连接到我的应用程序(即卡尺、体重秤等),而不是绑定到特定的品牌或型号,因此在客户端,我使用带有通用方法的接口(Delphi 通过通用接口的异步事件,delphi,asynchronous,delphi-2007,tcomport,Delphi,Asynchronous,Delphi 2007,Tcomport,我必须将多个测量设备连接到我的应用程序(即卡尺、体重秤等),而不是绑定到特定的品牌或型号,因此在客户端,我使用带有通用方法的接口(QueryValue)。设备通过COM端口连接,并以异步方式访问: 请求一个值(=发送一个特定的字符序列 COM端口) 等待答复 在“业务”方面,我的组件在内部使用TComPort,数据接收事件是TComPort.OnRxChar。我想知道如何通过接口触发此事件?以下是我迄今为止所做的工作: IDevice = interface procedure QueryV
QueryValue
)。设备通过COM端口连接,并以异步方式访问:
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
。执行这种数据流的通常方法是什么?您可以向接口添加事件属性
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;
然后像通常一样,在ComPortRxChar
的末尾调用FMyEvent
处理程序(如果已分配)
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;
你能冲洗一下吗?在
t设备中
如何将FMyEvent
连接到Get/SetMyEvent
?如果在TDevice.ComPortRxChar
方法中,我写如果赋值(FMyEvent),那么FMyEvent(Self)代码>(就像我以前做的-我的意思是没有接口),什么时候Get/SetMyEvent
是隐含的?谢谢!我就是这样理解的;)这是一个非常好的解决方案,但我仍然看到了一个缺点:由于我只在客户端使用接口,而不使用实现(这是主要目标),EventHandler
中是否有办法将发送方
转换为IDevice
?否则,我应该将IDevice变量(您在按钮1click
中的“id”)声明为类变量。我的示例将Sender转换为IDevice。我不明白为什么IDevice应该是一个类变量……你的IDevice的生命周期是什么?在EventHandler
中,TDevice(Sender)
与TDevice
类型紧密耦合,但它不应该。与id:=TDevice.Create相同
在按钮1中单击
方法,但举例来说,没问题,我使用了一个类型解析器,它完成所有依赖项注入工作。如果我无法将发送方
强制转换为预期类型,则类变量将在所有类方法中使用相同的变量。是否希望EventHandler参数具有接口类型?我认为可以使用IDevice参数声明处理程序过程类型,并使用它代替TNotifyEvent。如果您的IDevice是单例的,您可以完全避免使用Sender。