RPGle - 我希望我能用RPGLe做一些'反思'

时间:2013-10-30 14:25:53

标签: reflection ibm-midrange rpgle

我希望我能用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)相反;

反思会帮助我建立真正酷的apis。 有什么办法吗?

3 个答案:

答案 0 :(得分:3)

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

基本概念是这样的:如果您定义了一个具有所需格式的表,如果您的日期结构,使DS能够在外部定义,那么使用嵌入式SQL,您可以对表进行DESCRIBE或查询SYSCOLUMNS以获取您的字段定义,最好是在程序中。

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

答案 1 :(得分:2)

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

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

其中一个功能是 转储模块变量(QteDumpModuleVariables)API

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

答案 2 :(得分: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                             

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