Delphi XE6 - 我有一个Unit(EMAIL1.pas),可以进行相关处理。这是一个独立的单元,我可以合并到多个程序中。我的初始过程称为GetDetailsFromEmailAddress。它有两个参数,一个我查找的电子邮件地址和一个将更新的“数据组”,目前定义为var。这可以是一个记录或一个类,我真的不在乎。它只是一组相关的字符串(名字,姓氏,城市等)。我们称之为EmpRec。
我的挑战是这个过程创建了一个类的实例(JEDI VCL HTMLParser),它使用方法指针来调用方法(TableKeyFound)。此例程需要更新EmpRec。我不想更改此代码(HTMLPArser例程)以添加其他参数。我的UNIT创建了其他几个程序。所有这些都需要读取/更新EmpRec。我该怎么做?
我需要一种方法来“提升”在此UNIT中传递的变量EmpRec(GetDetailsFromEmailAddress)为GLOBAL,以便所有例程都可以访问或更改各种元素。我该怎么做?我真的不想将其定义为GLOBAL / Application wide变量。
下面的代码示例。那么..例程TableKeyFoundEx如何访问EmpRec变量?
procedure GetDetailsFromEmailAddress(Email: string; var EmpRec: TEmpRec);
begin
...
// Now create the HTML Parser...
JvHtmlParser1 := TJvHTMLParser.Create(nil);
// On event KeyFoundEx, call Parsehandlers.TableKeyFoundEx;
JvHtmlParser1.OnKeyFoundEx := ParseHandlers.TableKeyFoundEx;
...
end.
procedure TParseHandlers.TableKeyFoundEx(Sender: TObject; Key, Results, OriginalLine: String; TagInfo: TTagInfo;
Attributes: TStrings);
begin
..
// NEED ACCESS to EmpRec here, but can't change procedure definition
end;
答案 0 :(得分:1)
我会采用两种不同的方法:
使用解析器的Tag
属性:
procedure GetDetailsFromEmailAddress(Email: string; var EmpRec: TEmpRec);
begin
...
JvHtmlParser1 := TJvHTMLParser.Create(nil);
JvHtmlParser1.OnKeyFoundEx := ParseHandlers.TableKeyFoundEx;
JvHtmlParser1.Tag := NativeInt(@EmpRec);
...
end;
procedure TParseHandlers.TableKeyFoundEx(Sender: TObject; Key, Results, OriginalLine: String; TagInfo: TTagInfo; Attributes: TStrings);
var
EmpRec: PEmpRec; // assuming PEmpRec = ^TEmpRec
begin
EmpRec := PEmpRec(TJvHTMLParser(Sender).Tag);
...
end;
使用一点TMethod
黑客将记录DIRECTLY直接传递给事件处理程序:
// Note: this is declared as a STANDALONE procedure instead of a class method.
// The extra DATA parameter is where a method would normally pass its 'Self' pointer...
procedure TableKeyFoundEx(Data: Pointer: Sender: TObject; Key, Results, OriginalLine: String; TagInfo: TTagInfo; Attributes: TStrings);
var
EmpRec: PEmpRec; // assuming PEmpRec = ^TEmpRec
begin
EmpRec := PEmpRec(Data);
...
end;
procedure GetDetailsFromEmailAddress(Email: string; var EmpRec: TEmpRec);
var
M: TMethod;
begin
...
JvHtmlParser1 := TJvHTMLParser.Create(nil);
M.Code := @TableKeyFoundEx;
M.Data := @EmpRec;
JvHtmlParser1.OnKeyFoundEx := TJvKeyFoundExEvent(M);
...
end;
答案 1 :(得分:0)
除了Remy提供的两个选项之外,您还可以派生出TJvHTMLParser
的子类。
type
PEmpRec = ^TEmpRec;
TMyJvHTMLParser = class(TJvHTMLParser)
private
FEmpRec: PEmpRec;
public
constructor Create(EmpRec: PEmpRec);
end;
....
constructor TMyJvHTMLParser.Create(EmpRec: PEmpRec);
begin
inherited Create(nil);
FEmpRec := EmpRec;
end;
创建解析器时,请执行以下操作:
procedure GetDetailsFromEmailAddress(Email: string; var EmpRec: TEmpRec);
var
Parser: TMyJvHTMLParser;
begin
Parser := TMyJvHTMLParser.Create(@EmpRec);
try
Parser.OnKeyFoundEx := ParseHandlers.TableKeyFoundEx;
....
finally
Parser.Free;
end;
end.
在OnKeyFoundEx
中,您将Sender
转换回解析器类型以获取对记录的访问权限:
procedure TParseHandlers.TableKeyFoundEx(Sender: TObject; ...);
var
EmpRec: PEmpRec;
begin
EmpRec := (Sender as TMyJvHTMLParser).FEmpRec;
....
end;