• 第九章: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

  • 相关阅读:
    svg圆弧进度条demo
    canvas圆弧、圆环进度条实现
    angularjs与pagination插件实现分页功能
    CSS布局:居中的多种实现方式
    新闻滚动demo
    移动端rem设置字体
    angularjs自定义指令通用属性详解
    浅谈angularjs绑定富文本出现的小问题
    jquery.validate使用攻略(表单校验)
    Typescript 享元模式(Flyweight)
  • 原文地址:https://www.cnblogs.com/Farseer1215/p/821841.html
Copyright © 2020-2023  润新知