AX提供了一些内置函数用来获取数据的类型,比如Typeof(),比如ClassIdGet(),TypeId().
这里只讨论一下TypeId(),查了半天都没找到关于这个函数的描述,倒是Inside AX这本书对TypeOf()有所描述:
Typeof()这个系统函数以变量实例为入参,返回入参对应的基本类型,比如下面的例子:
int
i
=
123
;
str s
=
"
Hello world
"
;
MyClass c;
Guid g
=
newGuid();
![](/Images/OutliningIndicators/None.gif)
print typeOf(i);
//
Prints Integer
print typeOf(s);
//
Prints String
print typeOf(c);
//
Prints Class
print typeOf(g);
//
Prints Guid
pause;
它的返回值是Types这个系统枚举类型的一个值,该枚举类型为X++中所有的基本类型包含一个值。当然我们可以用如下方法打印出Types这个系统枚举类型对应的值。
static
void
Types(Args _args)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
DictEnum dictEnum = new DictEnum(enumNum(Types));
int i;
;
for(i=0;i<dictEnum.values();i++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
info(int2str(dictEnum.index2Value(i)));
info(dictEnum.index2Label(i));
}
![](/Images/OutliningIndicators/InBlock.gif)
}
接下来再看TypeId这个函数,在Global这个类中我们可以看到有如下方法:
/**/
/*
Returns a valid Extended Data Type Id, given the argument in the form the system function typeId returns
*/
static
extendedTypeId typeId2ExtendedTypeId(
int
_extendedType)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if ((_extendedType & 0xffff) != Types::UserType)
throw error(strfmt("@SYS26445",funcname()));
![](/Images/OutliningIndicators/InBlock.gif)
return _extendedType >> 16 & 0xffff;
}
当然还有个类似的方法:
/**/
/*
Returns a valid Enum Id, given the argument in the form the system function typeId returns.
Consider use the enumNum intrinsic function, instead of this function!
*/
static
enumId typeId2EnumId(enumId _enumId)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if ((_enumId & 0xffff) != Types::Enum)
throw error(strfmt("@SYS23815",funcname()));
![](/Images/OutliningIndicators/InBlock.gif)
return _enumId >> 16 & 0xffff;
}
从函数说明可以看出,这两个方法的入参都是函数TypeId()的返回值。我试了一下TypeId()这个方法的入参只能是EDT或者Enum类型(当然由于没有看到相关的文档,只是我测试的结果,可能不准确),其他类型做入参的时候就报错说:
*** 错误: 97,FunctionModuleID 的参数不是模块。
从上面的两个函数我们就可以推测出typeId()这个函数的返回值是什么了。
if
((_extendedType
&
0xffff
)
!=
Types::UserType)
throw
error(strfmt(
"
@SYS26445
"
,funcname()));
typeId()函数的返回值与0xffff做按位与运算显然是要屏蔽其返回值的高16位,从而取得低16位,而与运算的结果与Types类型做比较,显然其低16位对应的是EDT类型(或者枚举类型)对应的原始类型,当然枚举类型对应的是Types::Enum,EDT类型对应的是Types::UserType.
return
_extendedType
>>
16
&
0xffff
;
右移16位,然后跟0xffff按位与,返回的是EDT类型(或者枚举类型)的ID,那显然typeId()方法返回值的高16位对应的是EDT类型(或者枚举类型)的ID了。
猜想的话,这些信息应该存在了AOD文件里,typeId()这个函数取得了该信息。
如果用typeId来取得EDT类型的Id,代码应该类似下面代码的样子:
typeId2ExtendedTypeId(typeId(AccountNum));
要调用两个函数,其实如果单纯取得EDT类型或者Enum类型的ID不需要这么周折,完全可以用一个内置函数来实现:
extendedTypeNum(AccountNum);
当然Enum有对应的EnumNum()这个内置函数,看上去后面的方法简洁多了。
typeId()这个方法还是有其用武之地的,在有些场景下需要传入的参数带有其原始数据类型信息,比如最常见的Runbase框架下通过代码添加控件的情况,服务端代码需要知道客户端代码是否为UserType(即:EDT类型)然后做相应的处理,这时用typeId()这个方法就方便多了,否则客户端每次调用还要传一个参数过去表示是否为UserType,估计会不怎么爽,呵呵。
当然typeId()这个方法可能还有其他用武之地。