Цитата:
Сообщение от
belugin
Если оно неопределенность на этапе компиляции, то это не привидение типов. В рантайме он уже своего собственного типа. Чего вы хотите добиться?
Как бы да, но не совсем. По крайней мере для переменных табличного типа в аксапте это не совсем так. Видимо мы имеем пример "дырявой абстракции" когда табличные переменные должны вести себя как классы, но так не происходит в реальности.
Изначально я пытался порешать вот эту проблему:
http://sashanazarov.blogspot.com/201...-fails-on.html
Для решения написал метод в Global (он как раз решает проблему описанную в блоге sashanazarov - позволяет обойти баги ядра)
X++:
// обходим баг вызова orig() для табличек с наследованием
// [url]http://sashanazarov.blogspot.com/2014/01/dynamics-ax-2012-orig-method-fails-on.html[/url]
// [url=http://axforum.info/forums/showthread.php?p=328140#post328140]Опасный orig[/url]
public static anyType origFieldValue_MRC(Common _common, FieldId _fieldId)
{
TableId tableId;
TableId tableId4Field;
FieldName fieldName;
Common commonCasted;
Common commonOrig;
DictTable dictTable;
anytype ret;
;
if (_common.RecId == 0)
{ // обходим баг
// [url=http://axforum.info/forums/showthread.php?p=328140#post328140]Опасный orig[/url]
commonOrig = _common.orig();
commonOrig.doClear();
ret = commonOrig.(_fieldId);
}
else
{
dictTable = new DictTable(_common.TableId);
if (!(dictTable && dictTable.supportInheritance()))
{ // обычная табличка без наследования - все как обычно
commonOrig = _common.orig();
ret = commonOrig.(_fieldId);
}
else
{ // обходим баг
// [url]http://sashanazarov.blogspot.com/2014/01/dynamics-ax-2012-orig-method-fails-on.html[/url]
// решаем проблемы с получением значений из родительских табличек для orig() буфера
// ищем tableId в иерархии наследования для которой первой определено поле _fieldId т.е. ту для которой оно было введено, а не отнаследовано.
fieldName = fieldId2name(_common.TableId, _fieldId);
tableId4Field = _common.TableId;
if(fieldName)
{
tableId = dictTable.extends();
while(tableId)
{
dictTable = new DictTable(tableId);
if (fieldName2id(tableId, fieldName))
{
tableId4Field = tableId;
}
else
{
break;
}
tableId = dictTable.extends();
}
}
if (tableId4Field)
{
commonCasted = SysDictTable::as(_common, tableId2name(tableId4Field));
commonOrig = commonCasted.orig();
ret = commonOrig.(_fieldId);
}
else
{
// не должны сюда попасть. Можно кидать исключение.
commonOrig = _common.orig();
ret = commonOrig.(_fieldId);
}
}
}
return ret;
}
иллюстрация работы метода origFieldValue_MRC - джоб:
X++:
// [url]http://sashanazarov.blogspot.com/2014/01/dynamics-ax-2012-orig-method-fails-on.html[/url]
static void reproOrigBug_MRC(Args _args)
{
CompanyInfo companyInfo;
DirPartyTable dirPartyTable;
Common common5;
Common common6;
anytype any;
;
select firstOnly companyInfo;
info(strFmt("Поле СompanyInfo.DataAreaId (системное. Определено на СompanyInfo). Значение \"%1\"", companyInfo.DataAreaId));
info(strFmt("Поле СompanyInfo.VATNum (не наследовано). Значение \"%1\"", companyInfo.VATNum));
info(strFmt("Поле СompanyInfo.Name (наследовано из DirPartyTable - от головной таблички в иерархии наследования). Значение \"%1\"", companyInfo.Name));
info(strFmt("Поле СompanyInfo.PhoneticName (наследовано из DirOrganizationBase - от промежуточной таблички в иерархии наследования. 1-й уровень наследования). Значение \"%1\"", companyInfo.PhoneticName));
info(strFmt("Поле СompanyInfo.DEL_RelationTypeName_OMInternalOrg (наследовано из OMInternalOrganization - от промежуточной таблички в иерархии наследования. 2-й уровень наследования). Значение \"%1\"", companyInfo.DEL_RelationTypeName_OMInternalOrg));
info("");
info("Теперь проверяем работу Orig()");
info("");
info("1. Обычный вызов companyInfo.orig().FieldName - для полей из таблиц родителей - теряем значения");
info(strFmt("companyInfo.orig().DataAreaId = \"%1\"", companyInfo.orig().DataAreaId));
info(strFmt("companyInfo.orig().VATNum = \"%1\"", companyInfo.orig().VATNum));
info(strFmt("companyInfo.orig().Name = \"%1\" %2", companyInfo.orig().Name, (companyInfo.orig().Name ? "" : "Потеряли значение !")));
info(strFmt("companyInfo.orig().PhoneticName = \"%1\" %2", companyInfo.orig().PhoneticName, (companyInfo.orig().PhoneticName ? "" : "Потеряли значение !")));
info(strFmt("companyInfo.orig().DEL_RelationTypeName_OMInternalOrg = \"%1\" %2", companyInfo.orig().DEL_RelationTypeName_OMInternalOrg, (companyInfo.orig().DEL_RelationTypeName_OMInternalOrg ? "" : "Потеряли значение !")));
info("");
dirPartyTable = companyInfo as DirPartyTable;
info("2. Явно приводим тип к табличной переменной другого типа. dirPartyTable = companyInfo as DirPartyTable. Вызов dirPartyTable.orig().FieldName. Лечит проблему но неудобно использовать. Надо помнить из какой таблички пришло поле в иерархии наследования. Держать в коде отдельную табличную переменную другого типа.");
info(strFmt("dirPartyTable.orig().DataAreaId = \"%1\"", dirPartyTable.orig().DataAreaId));
info(strFmt("dirPartyTable.orig().VATNum - НЕПРИМЕНИМО" /*, dirPartyTable.orig().VATNum*/));
info(strFmt("dirPartyTable.orig().Name = \"%1\"", dirPartyTable.orig().Name));
info(strFmt("dirPartyTable.orig().PhoneticName - НЕПРИМЕНИМО" /*, dirPartyTable.orig().PhoneticName*/));
info(strFmt("dirPartyTable.orig().DEL_RelationTypeName_OMInternalOrg - НЕПРИМЕНИМО" /*, dirPartyTable.orig().DEL_RelationTypeName_OMInternalOrg*/));
info("");
info("3. Попытка достать через common.orig() и прочие танцы с бубном - не помогло");
common5 = null;
common6 = null;
common5 = new SysDictTable(tableNum(DirPartyTable)).makeRecord(); // тип DirPartyTable
common5.data(companyInfo); // тип DirPartyTable , но это не помогает вытащить правильное значение
common6 = common5.orig(); // тип DirPartyTable , но это не помогает вытащить правильное значение
info(strFmt("common6.(fieldNum(DirPartyTable, Name)) = \"%1\"", common6.(fieldNum(DirPartyTable, Name))));
common5 = null;
common6 = null;
common5 = new SysDictTable(tableNum(DirPartyTable)).makeRecord(); // тип DirPartyTable , но это не помогает вытащить правильное значение
common5.data(companyInfo.orig()); // вот тут уже при вызове Orig() значение потеряно
common6 = common5;
info(strFmt("common6.(fieldNum(DirPartyTable, Name)) = \"%1\"", common6.(fieldNum(DirPartyTable, Name))));
info("");
info("4. Игры с приведением типов через переменную с типом anyType - все хорошо, но неудобно использовать.");
any = new SysDictTable(tableNum(DirPartyTable)).makeRecord(); // any - тип DirPartyTable
any = companyInfo; // any - все равно тип DirPartyTable - в этот момент происходит "приведение" типа.
common5 = any; // common5 - тип DirPartyTable
common6 = common5.orig(); // common6 - тип DirPartyTable
info(strFmt("common6.(fieldNum(DirPartyTable, Name)) = \"%1\"", common6.(fieldNum(DirPartyTable, Name))));
info("");
info("5. Достаем значение вызовом origFieldValue_MRC(companyInfo, ...) - все нормально. Удобно использовать.");
info(strFmt("origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, DataAreaId)) = \"%1\"", origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, DataAreaId))));
info(strFmt("origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, VATNum)) = \"%1\"", origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, VATNum))));
info(strFmt("origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, Name)) = \"%1\"", origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, Name))));
info(strFmt("origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, PhoneticName)) = \"%1\"", origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, PhoneticName))));
info(strFmt("origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, DEL_RelationTypeName_OMInternalOrg)) = \"%1\"", origFieldValue_MRC(companyInfo, fieldnum(CompanyInfo, DEL_RelationTypeName_OMInternalOrg))));
info("");
}