当前位置: 首页 > news >正文

第九章: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的类声明如下所示:
None.gif class  AxSalesTable extends AxInternalBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    SalesTable      salesTable;
ExpandedBlockEnd.gif}
在Ax<Table>类中,必须为相关表的每一个字段创建一个实例方法。方法名必须与字段名相同,以parm为前缀,并且必须使用如下模板:
None.gif public  DataType parmFieldName(DataType _fieldName 
None.gif
=  literal)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
if (!prmisdefault(_fieldName))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.setField(fieldNum(TableName,FieldName), _fieldName);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
return tableName.fieldName;
ExpandedBlockEnd.gif}
如果该实例方法执行的时候不用参数,会返回字段的值,如果用参数执行该方法,setField方法会被执行,参数为表字段的ID和传入的参数。
类AxInternalBase的实例方法setField查看该字段是否已经被设定了某个特定的值,如果没有设定会给该字段分配当前值。同时,更新其他已经分配了值的一系列字段。setField方法的逻辑如9-4所示。
AIF4.png
图9-4.setField方法的逻辑流程图
在类AxSalesTable的parmCustAccount方法体中可以看一个setField方法的具体实现(译注:原文缩减了该方法,这里将方法体全部列出):
None.gif public  str parmCustAccount(str _custAccount  =   '' )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    DictField dictField;
InBlock.gif    ;
InBlock.gif
InBlock.gif    
if (!prmisdefault(_custAccount))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        dictField 
= new DictField(tablenum(SalesTable),fieldnum(SalesTable, CustAccount));
InBlock.gif        
if(this.valueMappingInbound())
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.validateInboundString(_custAccount, dictField, this.mapPolicy().xMLMapCustAccount());
InBlock.gif            _custAccount 
= this.axCustAccount(_custAccount);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.validateInboundString(_custAccount, dictField);
ExpandedSubBlockEnd.gif        }

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

InBlock.gif
InBlock.gif    
if (this.valueMappingOutbound())
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return this.axCustAccount(salesTable.CustAccount);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return salesTable.CustAccount;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

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

InBlock.gif
// Additional code goes here.
ExpandedBlockEnd.gif
}
由于这个方法可能会被执行很多次, isMethodExecuted 方法用于探测该方法是否被执行过并且该字段是否被赋了某个值, isMethodExecuted 方法的逻辑如图9-5所示
AIF5.png
图9-5.方法 isMethodExecuted 的逻辑流程
如果依赖于其他字段(译注:原文为Dependencies on other fields ,意思是如果当前字段依赖于其他字段的话,就按如下方式执行)必须按如下方式编程
None.gif this .setAnotherFieldName();
None.gif
None.gif
if  ( this .isFieldSet(fieldNum(TableName,
None.gif AnotherFieldName)))
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
this.fieldName(newValue);
ExpandedBlockEnd.gif}
首先,需要执行当前字段所依赖字段的set方法,如果该字段所依赖的字段更改了,该方法给其赋新值。然后需要判断依赖字段是否被赋予了某个新值。如果赋了新值,则给当前字段赋新值。可以看一下类 AxSalesTablesetPaymMode 方法的实现:
None.gif protected   void  setPaymMode()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
if (this.isMethodExecuted(funcname(), fieldnum(SalesTable, PaymMode)))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
this.setInvoiceAccount();
InBlock.gif
InBlock.gif    
if (this.isFieldSet(fieldnum(SalesTable, InvoiceAccount)))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.parmPaymMode(this.invoiceAccount_CustTableRecord().PaymMode);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

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

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif       super();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
return tableName;
ExpandedBlockEnd.gif}
currentRecord调用super执行类 AxInternalBase 的实例方法currentRecord,实例方法 currentRecord 的逻辑如图9-6所示:
AIF6.png
图9-6. currentRecord 方法的逻辑流程
可以看一下类AxSalesTable的currentRecord方法的实现:
None.gif protected  SalesTable currentRecord(SalesTable
None.gif _salesTable 
=  salesTable)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
if (!prmisdefault(_salesTable))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super(_salesTable);
InBlock.gif        salesTable 
= _salesTable;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super();
ExpandedSubBlockEnd.gif    }

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

InBlock.gif    
return this.currentRecord();
ExpandedBlockEnd.gif}
setCurrentRecordFromExternal 实例方法执行 currentRecord 方法,并清除所有内部变量以便准备一个新的对象来应对新纪录的更改。
为确保在插入或更新记录之前调用所有的默认方法,必须重写类 AxInternalBasesetTableFields 方法,该方法应包含对所有默认方法的调用。可以看一下类 AxSalesTablesetTableFields 方法的部分实现:
None.gif protected   void  setTableFields()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    SalesTableLinks     salesTableLinks;
InBlock.gif    ;
InBlock.gif    super();
InBlock.gif
InBlock.gif    useMapPolicy 
= false;
InBlock.gif
InBlock.gif    
this.setCashDisc();
InBlock.gif    
this.setCommissionGroup();
InBlock.gif    
this.setContactPersonId();
InBlock.gif    
this.setCurrencyCode();
InBlock.gif    
this.setCustAccount();
InBlock.gif    
this.setCustGroup();
InBlock.gif    
this.setDeliveryAddress();
InBlock.gif    
this.setDeliveryCity();
InBlock.gif
// And so ondot.gif
InBlock.gif

转载于:https://www.cnblogs.com/Farseer1215/archive/2007/07/22/821841.html

相关文章:

  • 微信登陆
  • 文本相似度计算--余弦定理和广义Jaccard系数
  • 结构型模型Bridge
  • PHP实现程序单例执行
  • Visual C#.Net网络程序开发-Tcp篇(3)
  • [New Portal]Windows Azure Virtual Machine (3) 在VM上挂载磁盘
  • ajax.net 我曾经轻视了他,郁闷。
  • 彻底去除Win10“快速访问”
  • 网络服务器时间发布地址
  • 《Python地理数据处理》——2.3 变量
  • 只能使用数组初始值设定项表达式为数组类型赋值。请尝试改用新的表达式
  • 《Total Commander:万能文件管理器》——12.3.高人高见
  • 在C#中应用哈希表(Hashtable)
  • 《Python数据可视化编程实战》——5.2 创建3D柱状图
  • c#.net中参数修饰符ref,out ,params的区别
  • [NodeJS] 关于Buffer
  • 2017年终总结、随想
  • Apache Zeppelin在Apache Trafodion上的可视化
  • gcc介绍及安装
  • gitlab-ci配置详解(一)
  • Java 最常见的 200+ 面试题:面试必备
  • Java多线程(4):使用线程池执行定时任务
  • OSS Web直传 (文件图片)
  • Python实现BT种子转化为磁力链接【实战】
  • React as a UI Runtime(五、列表)
  • Redux系列x:源码分析
  • Service Worker
  • springboot_database项目介绍
  • SSH 免密登录
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 读懂package.json -- 依赖管理
  • 服务器之间,相同帐号,实现免密钥登录
  • 记一次删除Git记录中的大文件的过程
  • 简析gRPC client 连接管理
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 最简单的无缝轮播
  • 2017年360最后一道编程题
  • ​linux启动进程的方式
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #QT(串口助手-界面)
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (Ruby)Ubuntu12.04安装Rails环境
  • (分布式缓存)Redis持久化
  • (分布式缓存)Redis哨兵
  • (一)认识微服务
  • (转)3D模板阴影原理
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)IOS中获取各种文件的目录路径的方法
  • ****Linux下Mysql的安装和配置
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • /dev/sda2 is mounted; will not make a filesystem here!
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)