第九章:XML文档集成AxInternalBase API

本文仅供AX从业者和爱好者交流之用,由于原文版权问题,请勿转载。
AxInternalBase API
创建Ax<Table>类的目的是当创建和更新AX表中的记录时有一个可用的API。AxInternalBase API的设计目标如下:
1.该API易于使用
2.该API必须处理相关字段。当一个字段更新时可以应用默认值。比如,当更改销售订单的客户账户时,将地址字段从客户记录复制到销售订单记录时,地址字段应该可以用默认值
3.该API必须处理字段更新的顺序。比如,发票帐号字段是一个相关字段,当客户账户改变时,该字段应该变成默认值。
4.字段默认值可能不总是提供期望的最终结果。考虑一个例子:首先更新如果发票帐号,其他字段的值是默认的,然后更新客户帐号,其他字段的值是默认的,这样默认值将会重写显式提供的发票帐号字段。
5.该API必须能从编码规则取得编码或者标识符。比如,当创建一个销售订单时,销售订单号必须从销售订单的编码规则中取得。处理这些的逻辑在这些类中实现。
新的Ax<Table>类必须继承自AxInternalBase类。AxInternalBase类追踪为了给表的某个字段设定一个特定的值都执行了哪些方法,可以外部或者内部实现追踪。外部的,比如,可以用一个特定的值调用AxSalesTable类的parmCustAccount方法。内部的,可以调用AxSalesTable的parmInvoiceAccount方法,因为它是个相关字段,当parmCustAccount 方法执行时,它应该变成默认值。通过监测执行的方法,AxinternalBase类确保外部设定的值不被重写。
类AxBC(译注:上下文都没提到过AxBC这个东东,应该就是Ax<Table>类)的声明中必须声明一个与AxBC相关的表类型的记录变量。因此AxSalesTable的类声明如下所示:
class AxSalesTable extends AxInternalBase
{
    SalesTable      salesTable;
}
在Ax<Table>类中,必须为相关表的每一个字段创建一个实例方法。方法名必须与字段名相同,以parm为前缀,并且必须使用如下模板:
public DataType parmFieldName(DataType _fieldName 
= literal)
{
    
if (!prmisdefault(_fieldName))
    
{
        
this.setField(fieldNum(TableName,FieldName), _fieldName);
    }

    
return tableName.fieldName;
}
如果该实例方法执行的时候不用参数,会返回字段的值,如果用参数执行该方法,setField方法会被执行,参数为表字段的ID和传入的参数。
类AxInternalBase的实例方法setField查看该字段是否已经被设定了某个特定的值,如果没有设定会给该字段分配当前值。同时,更新其他已经分配了值的一系列字段。setField方法的逻辑如9-4所示。

图9-4.setField方法的逻辑流程图
在类AxSalesTable的parmCustAccount方法体中可以看一个setField方法的具体实现(译注:原文缩减了该方法,这里将方法体全部列出):
public str parmCustAccount(str _custAccount = '')
{
    DictField dictField;
    ;

    
if (!prmisdefault(_custAccount))
    
{
        dictField 
= new DictField(tablenum(SalesTable),fieldnum(SalesTable, CustAccount));
        
if(this.valueMappingInbound())
        
{
            
this.validateInboundString(_custAccount, dictField, this.mapPolicy().xMLMapCustAccount());
            _custAccount 
= this.axCustAccount(_custAccount);
        }

        
else
        
{
            
this.validateInboundString(_custAccount, dictField);
        }


        
this.setField(fieldnum(SalesTable, CustAccount), _custAccount);
    }


    
if (this.valueMappingOutbound())
    
{
        
return this.axCustAccount(salesTable.CustAccount);
    }

    
else
    
{
        
return salesTable.CustAccount;
    }

}

 如果必须解决内在字段关系,就是当一个字段的值更改时表的另一个字段要设置成某个特定的值,必须为两个字段创建实例方法。方法名必须与字段名相同,用set作为前缀,并采用如下模板,加粗的文本必须用当前的表和字段名修改(译注:其中Table和FieldName为加粗的文本)。
protected void setFieldName()
{
    
if (this.isMethodExecuted(funcName(), fieldNum
(TableName, FieldName)))
    
{
        
return;
    }

// Additional code goes here.
}
由于这个方法可能会被执行很多次,isMethodExecuted 方法用于探测该方法是否被执行过并且该字段是否被赋了某个值,isMethodExecuted 方法的逻辑如图9-5所示

图9-5.方法isMethodExecuted 的逻辑流程
如果依赖于其他字段(译注:原文为Dependencies on other fields ,意思是如果当前字段依赖于其他字段的话,就按如下方式执行)必须按如下方式编程
this.setAnotherFieldName();

if (this.isFieldSet(fieldNum(TableName,
 AnotherFieldName)))
{
    
this.fieldName(newValue);
}
首先,需要执行当前字段所依赖字段的set方法,如果该字段所依赖的字段更改了,该方法给其赋新值。然后需要判断依赖字段是否被赋予了某个新值。如果赋了新值,则给当前字段赋新值。可以看一下类AxSalesTablesetPaymMode 方法的实现:
protected void setPaymMode()
{
    
if (this.isMethodExecuted(funcname(), fieldnum(SalesTable, PaymMode)))
    
{
        
return;
    }


    
this.setInvoiceAccount();

    
if (this.isFieldSet(fieldnum(SalesTable, InvoiceAccount)))
    
{
        
this.parmPaymMode(this.invoiceAccount_CustTableRecord().PaymMode);
    }

}

为了设置和获取当前记录,必须重写类AxSaelsTable的currentRecord 方法。重写必须使用如下模板
protected TableName currentRecord(TableName
 _tableName 
= tableName)
{
    
if (!prmisdefault(_tableName))
    
{
        super(_tableName);
        tableName 
= _tableName;
    }

    
else
    
{
       super();
    }


    
return tableName;
}
currentRecord调用super执行类AxInternalBase 的实例方法currentRecord,实例方法currentRecord 的逻辑如图9-6所示:

图9-6.currentRecord 方法的逻辑流程
可以看一下类AxSalesTable的currentRecord方法的实现:
protected SalesTable currentRecord(SalesTable
 _salesTable 
= salesTable)
{
    
if (!prmisdefault(_salesTable))
    
{
        super(_salesTable);
        salesTable 
= _salesTable;
    }

    
else
    
{
        super();
    }

    
return salesTable;
}
要更新一条已存在的记录,表记录必须通过表记录的实例方法传递给Ax<Table>对象,方法名必须与表名相同,并且必须采用如下模板:
public TableName tableName(TableName _tableName = tableName)
{
    
if (!prmisdefault(_tableName))
    
{
        
this.setCurrentRecordFromExternal(_tableName);
    }

    
return this.currentRecord();
}
setCurrentRecordFromExternal 实例方法执行currentRecord 方法,并清除所有内部变量以便准备一个新的对象来应对新纪录的更改。
为确保在插入或更新记录之前调用所有的默认方法,必须重写类AxInternalBasesetTableFields 方法,该方法应包含对所有默认方法的调用。可以看一下类AxSalesTablesetTableFields 方法的部分实现:
protected void setTableFields()
{
    SalesTableLinks     salesTableLinks;
    ;
    super();

    useMapPolicy 
= false;

    
this.setCashDisc();
    
this.setCommissionGroup();
    
this.setContactPersonId();
    
this.setCurrencyCode();
    
this.setCustAccount();
    
this.setCustGroup();
    
this.setDeliveryAddress();
    
this.setDeliveryCity();
// And so on

原文地址:https://www.cnblogs.com/Farseer1215/p/821841.html