在运行时从另一个程序读取非全局变量

Read non-global variable from another program in runtime

我想在堆栈的第 11 层访问第 5 层的变量。

两个级别属于不同的程序:

lvl    type       event              program                 include 
11     METHOD     SET_PERNRS_TAB     <my_program>            <my_include>.
...
05     FORM       PUT_PERNR          <ldb_program>          <ldb_include>.
04     FORM       %_ROOT             <ldb_program>          <ldb_include>.
...

这就是我目前的做法:

constants lc_ldb_pernr_tab   type string value `(LDB_PROGRAM)INDEX[]`.
field-symbols <lt_pernr_tab> type any table.

assign (lc_ldb_pernr_tab) to <lt_pernr_tab>.

现在我可以在另一个程序中使用 <lt_pernr_tab>,它是来自 LDB 的变量 index[] 的 'copy'。

这里的问题是它只对一些变量起作用,对其他变量不起作用...请在下面的 ldb 程序中找到两个变量的声明。

我试图从我的程序中获取它们的价值,但只有一个有效。

  1. 有效的那个,index
DATA: BEGIN OF COMMON PART $pnp-index$.
  DATA: BEGIN OF index OCCURS 1000,
          pernr LIKE pernr-pernr,
        END OF index.
DATA: END   OF COMMON PART.
  1. 没有的,index_all
  DATA: index_all TYPE t_t_pernr.

这意味着 (program)variable 的这个过程只适用于被 ldb 声明为“common part”的变量?

换句话说,当我在我的程序中时,不可能从 LDB 程序中获取 index_all 的内容,因为它不是 "common part"?

-> 给出一点上下文,index_all 有我需要的所有条目,而 index 只是 index_all 的一个分区。 LDB 遍历 index,完成后,它会用 index_all 的下一个索引更新它。

我认为 documentation 说明了一切:

For internal use only, the name in name can also have the form "(PROG)DOBJ", where "PROG" is the name of an ABAP program and "DOBJ" the name of a global data object of this program (these names are not case-sensitive). If the program "PROG" is loaded into the same internal session as the current program when the statement ASSIGN is executed, the data object "DOBJ" is found in this program and the field symbol points to this data object if the assignment was successful.

注意 "for internal use only",即这种特殊形式的 ASSIGN 可能会在任何未来的 ABAP 版本中被删除(但我怀疑)。

所以,您可能想要访问一个非 全局 的变量,即本地、实例属性或 private/protected 静态属性...

ASSIGN ('PROG(DOBJ)')common part 一起工作,因为它具有 全局 范围。请注意,通过声明 "common part".

的相同名称,属于同一 "group" (1) 的其他程序也可以在没有 ASSIGN 的情况下使用公共部分

如果您可以调整该程序(因为它是自定义的),则更愿意对其进行一些重构,以便可以从外部访问数据,而不是使用以下技巧。

如果您无法调整程序(因为它是标准程序),可以使用以下变通方法访问本地数据对象

假设这个程序是 "PROG",它包含过程 "X",其中包含您要读取的本地数据对象 "LOCVAR"。您可以使用 Enhancement Framework 来做到这一点。因此,要使其可从外部程序访问:

  • 在PROG中,声明一个全局数据引用变量(2),比如DATA ZZ_REF_LOCVAR TYPE REF TO DATA(建议:前缀"ZZ"以限制与程序未来补丁的冲突)
  • 在程序"X"的开头,通过代码ASSIGN ('LOCVAR') TO FIELD-SYMBOL(<zz_locvar>). zz_ref = ref #( <zz_locvar> ).初始化ZZ_REF_LOCVAR (3)
  • 在您自己的程序中,如果过程 "X" 当前在调用堆栈中,您可以检查 class CL_ABAP_GET_CALL_STACK,您现在可以访问全局数据引用使用此代码指向局部变量:FIELD-SYMBOLS <ref_locvar> TYPE REF TO DATA. FIELD-SYMBOLS <locvar>. ASSIGN ('(PROG)ZZ_REF_LOCVAR') TO <ref_locvar>. ASSIGN <ref_locvar>->* TO <locvar>.
  • 此解决方案的一个小变体是将 ZZ_REF_LOCVAR 声明为自定义 class 池中的静态 public 属性,并从标准程序 PROG 和您自己的程序访问它代码。

小心,如果未来的补丁删除局部变量,它可能不再工作。无论如何,这句话对全局变量也有效。


(1) 注:a "group" of programs is formed of programs called via PERFORM IN PROGRAM or CALL SUBSCREEN by PROG, and they have a common memory area called "interface work area".

(2) 注意:我建议使用全局数据引用变量而不是全局字段符号,因为字段符号不能在像class pools.

这样的程序中全局声明

(3) 注意:程序开头的隐式增强"X"不能通过命名直接访问局部变量,因为它们的DATA是增强后的;解决方法是使用字段符号在 运行 时间访问局部变量。