Split construct method by models. Part2.
Last time we try to resolve problem with separate construct method by model in one layer using new future in ax delegate and event handler.
At this article try to resolve this problem using another way.
This way was got from Unit testing (source Classes\SysTestCase\testMethods + Classes\SysTest\invoke - try to find methods from object for specific mask), and now in AX 2012 we can find very similar way using name conversational in financial dimension (\Classes\DimensionEnabledType\getSystemDefinedDimensionsServer - try to find Views by name consist of specific mask). Lets try use this way.
From previous topic we have next conditions
- TestBaseClass - in model A01
- TestBaseClass01_Model01 in model A01
- TestBaseClass02_Model02 in model A02
We need write construct method, and this method must work when we try transfer model A01 to another application.
in TestBaseClass (model A01) we create new static method constructFromCode()
X++:
public static TestBaseClass constructFromCode(SalesTable _salesTable)
{
#define.codeConstructor('codeConstructor')
TestBaseClass ret;
SysDictClass sysDictClass = new SysDictClass(classNum(TestBaseClass));
DictMethod method = null;
Set methods;
SetEnumerator se;
Set orderedSet = new Set(Types::String);
ExecutePermission executePermission;
;
// source Classes\SysTestCase\testMethods
methods = sysDictClass.methods(false, true, false);
se = methods.getEnumerator();
while (se.moveNext())
{
method = se.current();
if (method
&& method.accessSpecifier() == AccessSpecifier::public
&& method.returnType() != Types::void
&& method.parameterCnt() == 1)
{
if (strStartsWith(method.name(), #codeConstructor))
{
orderedSet.add(method.name());
}
} // if methods
} // while
// part 2 - split init call
// source \Classes\SysTest\invoke
executePermission = new ExecutePermission();
executePermission.assert();
se = orderedSet.getEnumerator();
while (se.moveNext())
{
// part 2.1 call methods
ret = sysDictClass.callStatic(se.current(), _salesTable);
if (ret)
break;
}
CodeAccessPermission::revertAssert();
// init default value
if (!ret)
{
ret = new TestBaseClass();
}
ret.parmSalesTable(_salesTable);
return ret;
}
next we need create 2 additional methods in TestBaseClass
codeConstructorClass01_M01 in A01 model
X++:
public static TestBaseClass codeConstructorClass01_M01(SalesTable _salesTable)
{
TestBaseClass01_Model01 testBaseClass01_Model01 = TestBaseClass01_Model01::construct();
if (testBaseClass01_Model01.findDetermination(_salesTable))
return testBaseClass01_Model01;
return null;
}
and codeConstructorClass02_M02 in A02 model
X++:
public static TestBaseClass codeConstructorClass02_M03(SalesTable _salesTable)
{
TestBaseClass02_Model02 testBaseClass02_Model02 = TestBaseClass02_Model02::construct();
if (testBaseClass02_Model02.findDetermination(_salesTable))
return testBaseClass02_Model02;
return null;
}
let's create and run a job to check our implementation
X++:
[COLOR=blue]static void TestBaseClass2(Args _args)
{
SalesTable salesTable; // cursor
TestBaseClass baseClass;
setPrefix("SalesInfo2");
while select salesTable
{
baseClass = TestBaseClass::constructFromCode(salesTable);
baseClass.showInfo();
}
info("done");
}
and results of working
Results
Summary: we can use various way to create construct method without depends from models and layers.