5

我希望我可以使用 RPGLe 进行一些反思。通过反思,我的意思是:“在运行时确定对象能力的过程或机制。”

想象一下你有这个数据结构:

 D DS_Format       DS                  Qualified Based(pDS_Format)
 D  Type                         20I 0 Inz(1)
 D  Label                        50A   Inz('myLabel')
 D  Description                5000A   Inz('myDescription')        

使用反射 api,我可以这样做:

Reflection_ListSubfields(DS_Format); 

=> 返回这个数组:{ 'Type', 'Label', 'Description' }

然后,我可以这样做:

Reflection_GetSubfield(DS_Format : 'Label'); => return 'myLabel'

我希望我也可以这样做:

Reflection_GetSubfieldType(DS_Format : 'Label'); => return 'A'
Reflection_GetSubfieldLength(DS_Format : 'Label'); => return 50
Reflection_GetSubfieldPrecision(DS_Format : 'Type'); => return 0

有了这个,我希望我可以做这样的事情(做一些小工作):

SerializeXml(DS_Format); //I build xml with one line of code !

并得到:

<DS_Format>
    <Type>1</Type>
    <Label>myLabel</Label>
    <Description>myDescription</Description>
</DS_Format>

反之, DeserializeXml(myXml);

反射将帮助我构建非常酷的 api。有什么办法吗?

4

3 回答 3

3

我一直在考虑其中的一些概念,并且可能有一个解决方法。(我现在还没有时间写一个完整的答案并充实细节,但等着你看看有没有希望 ;-) 虽然有些人可能认为这是作弊。)

基本概念是这样的:如果您定义了一个具有所需格式的表,如果您的天结构允许外部定义 DS,那么您可以使用嵌入式 SQL 描述该表或查询 SYSCOLUMNS 以获取您的字段定义,最好是在过程中。

诚然,这与反省不同,但可以完成很多相同的事情。人们可能只会在有限的情况下这样做。我相信其他人会指出各种各样的问题,但这里的重点是这是可能的。

于 2013-10-30T16:33:18.220 回答
2

下面是 WarrenT 想法的一个非常简单的实现。

create table ds_format
(
   Type        numeric(20, 0),
   Label       char(50),
   Description char(5000)
);

SQL 描述区域的常量:

D SQL_NUM         C                   99

在返回字段名称数组的 SQLRPGLE 模块中实现 Reflection_ListSubfields:

P Reflection_ListSubfields...                         
P                 B                                
 *                                                 
D                 PI            80A   Dim(SQL_NUM) 
D  name                         30A   Const
 *                                                 
D tableName       S                   Like(name)   
D i               S              3S 0 Inz          
D fieldList       S             80A   Dim(SQL_NUM) 
 /free                                             
    EXEC SQL include SQLDA;                        

    // retrieve description of the table                                           
    tableName = name;                              
    EXEC SQL describe table :tableName into :sqlda;

    // loop over all fields and
    // retrieve the name                                                   
    for i = 1 to SQLD;                             
       SQLVAR = SQL_VAR(i);                        
       fieldList(i) = SQLNAME;                     
    endfor;                                        

    return fieldList;
 /end-free           
P                 E  

现在是 Reflection_GetSubfield 的一个非常粗略的实现,它以字符串形式返回值:

P Reflection_GetSubfield...                                   
P                 B                                        
 *                                                         
D                 PI         32000A   Varying              
D  dataStruct                     *   Const                
D  name                         30A   Const
D  fieldName                    80A   Const                
 *                                                         
D tableName       S                   Like(name)           
D i               S              3S 0 Inz                  
D start           S              6S 0 Inz(1)               
D length          S              6S 0 Inz(1)               
D p_str           S               *                        
D str             S          32000A   Based(p_str)         
D value           S          32000A   Varying              
 /free                                                 
    EXEC SQL include SQLDA;                        

    // retrieve description of the table                                           
    tableName = name;                                  
    EXEC SQL describe table :tableName into :sqlda;    

    // loop over all fields
    for i = 1 to SQLD;                                 
       SQLVAR = SQL_VAR(i);                            

       length = SQLLEN;                                

       // Zoned decimal?
       if SQLTYPE = 489;                               
          length = SQLLEN / 256;                       
       endif;                                          

       // field found?                                                       
       if SQLNAME = fieldName;                         
          leave;                                       
       endif;

       start += length;                             
    endfor;                                            

    p_str = dataStruct;                                 

    // retrieve value from our string                                                
    value = %trim(%subst(str: start: length));  

    return value;                               
 /end-free                                      
P                 E                             

我想有了这些信息,实现其他三个程序就相对容易了。

于 2014-04-25T08:55:44.860 回答
2

我想知道调试 API 是否可以帮助至少获得您要求的一些行为......

http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/topic/apis/debug1.htm

包含的功能之一是转储模块变量 (QteDumpModuleVariables) A​​PI

当然,您的工作必须处于调试模式才能使用这些 API...

于 2014-02-19T21:13:55.427 回答