我有以下情况。
我制作了一个组件。我想在使用一种方法时从组件中获得一些反馈。
与component.Method(param1:callback function);
类似 到目前为止,一切都很好,有光泽。该项目有以下单位。
formMain - 可见表格。
dataModule - 使用组件。
表格主要需要传递给datamodule一个回调函数来接收他的反馈。此回调函数是与组件不同的函数(具有更多参数)。
我不知道该怎么做。
TFeedBackProcedure = procedure(param1 : Integer) of object;
TFeedBackProcedureByTypeOf = procedure(aTypeOf : Integer; param1 : Integer) of object;
// component
procedure Syncro(feedBack : TFeedBackProcedure);
begin
//somewhere inside
for i := 0 to 15 do begin
feedBack(i);
end;
end;
// the feeedback received so far when someone use the Syncro procedure is the value of i
// the datamodule
// inside of a method I need to pass also the i received from compoent also a typeof value used only inside datamodule
procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf); // the extended callback
begin
typeof = 1;
if component.Syncro(???) then begin // <-------- how to ???
// do stuff
end;
end;
// the main form
// the real callback function
procedure TFormMain.Feddback(aTypeOf : Integer; param1: Integer);
begin
if aTypeOf = 0 then begin
label1.caption = IntToStr(param1);
end else begin
label2.caption = IntToStr(param1);
end;
end;
// usage of datamodule
procedure TFormMain.btn1Click(Sender: TObject);
begin
dataModule.UseMethod(Feddback);
end;
任何想法?任何其他方法来做到这一点? (我在FMX环境中也需要这个)
很多
勒兹
答案 0 :(得分:2)
如果您自己编写了组件,那么最简单的方法是更改TFeedbackProcedure
的类型声明,以便它也接受匿名方法(以及对象方法):
TFeedBackProcedure = reference to procedure(param1 : Integer);
这使您可以将扩展方法包装到位并调用它:
procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf);
var
_typeOf : integer;
begin
_typeOf = 1;
component.Syncro(procedure(AParam : integer)
begin
feedbackProcedure(_typeOf, AParam);
end);
end;
我只是简单地在这里调用方法,因为你的例子写了.Synchro
,好像它是一个返回布尔值的函数,实际上,你已经将它声明为一个简单的过程。
作为替代方案,如果您无法更改方法签名或将包装器添加到现有类,则始终可以编写包装类来执行此任务。我在这里展示了一个专用的包装器类,但您可以轻松地将这些字段和方法添加到任何合适的类中,以将功能包装到具有正确签名的对象方法中。
TCallbackContainer = class
private
FParam : integer;
FFeedbackProcByTypeOf : TFeedBackProcedureByTypeOf;
public
constructor Create(AProcByTypeOf : TFeedBackProcedureByTypeOf);
procedure WrapCallback(AParam:integer);
property IntParam : integer read FParam write FParam;
end;
实施:
constructor TCallbackContainer.Create(AProcByTypeOf : TFeedBackProcedureByTypeOf);
begin
FFeedbackProcByTypeOf := AProcByTypeOf;
end;
procedure TCallbackContainer.WrapCallback(AParam: Integer);
begin
FFeedbackProcByTypeOf(FParam, AParam);
end;
然后你可以这样称呼:
procedure UseMethod(feedbackProcedure : TFeedBackProcedureByTypeOf);
var
LCallbackContainer : TCallbackContainer;
begin
LCallBackContainer := TCallbackContainer.Create(feedbackProcedure);
try
LCallBackContainer.IntParam := 1;
component.Syncro(LCallbackContainer.WrapCallback);
finally
LCallBackContainer.Free;
end;
{ Or, make it FCallBackContainer and manage lifetime somehow...}
end;
与引用计数的匿名方法不同,您必须以某种方式管理LCallbackContainer
对象生存期。我已经将它显示为本地,如果.Synchro
实际上是完全同步的,那么就可以了,并且当它返回时你可以释放回调容器。如果。Synchro
实际上是一个异步方法,并且在它的工作完成之前返回,那么你需要一些方法来管理回调包装器的生命周期。
您还应避免命名变量TypeOf
,因为这会隐藏the standard method该名称。不推荐使用System.TypeOf
,但仍然可以避免这样的命名冲突。