Delphi作用域 - 在代码之间共享数据

时间:2014-09-08 22:20:07

标签: delphi scope

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;

2 个答案:

答案 0 :(得分:1)

我会采用两种不同的方法:

  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;
    
  2. 使用一点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;