Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

Опции темы Поиск в этой теме Опции просмотра
Старый 04.04.2018, 14:11   #1  
Blog bot is offline
Blog bot
22,324 / 771 (70) +++++++
Регистрация: 28.10.2006
sertandev: Using .NET attributes for D365 FO child class constructors

Previously, we used to define class constructors like below if we want to switch correct child class via a parameter :

public static AtTest constructFromCommon(Common _common) { AtTest ret;switch(_common.Tableid) { case tableNum(CustTable) : ret = new AtTest_Customer(_common); break; case tableNum(VendTable) : ret = new AtTest_Vendor(_common); break; }return ret;}Since AX 2012, we have the ability to create and use .NET attributes and in D365 FO they are widely used in the extension framework.

The constructor template given above is declared in the base class and child classes does not have any information on them about which table they are constructed from, which makes it not very readable. Moreover, to be able to remove a class from here or add another child class, we needed to modify the ‘switch’ clause via overlayering (in 2012), which is not very practical and may cause problems on code upgrades. In D365 FO, we have another concern of being ‘extendable’. It is possible to extended those old style constructs using method posthandlers but if a couple of different extensions extend the same method, things get a little bit messy.

For all that reasons, class attributes are the new way to define child class constructors and widely being used in newer D365 FO code. For an example, see the class “InventTransferPrintCommand” and its child classes.

Let create an example to understand it further. To be able to use attributes in class constructors, you need to define your attribute class first. It is done by extending the SysAttribute class and SysExtensionIAttribute interface, then declaring your attribute parameters as properties as shown in the template belown :

////// The AtTableNameAttribute is the attribute for AtTest classes./// class AtTableNameAttribute extends SysAttribute implements SysExtensionIAttribute{ TableName tableName; void new(TableName _tableName) { super(); tableName = _tableName; } /// /// Returns the key used for storing cached data for this attribute. /// /// /// A string representing the cache key. /// public str parmCacheKey() { return classStr(AtTableNameAttribute)+';'+tableName; } public TableName parmTableName(TableName _tableName = tableName) { tableName = _tableName; return tableName; } /// /// Determines if the same instance should be returned by the extension framework. /// /// /// true if the same instance should be returned; otherwise false. /// public boolean useSingleton() { return false; }}The parmCacheKey() method should return a unique key per class + parameter combination and used for caching the attribute class instances per parameter. Set singleton false if you do want to use an instance per parameter (in our case yes).

Another thing you can spot here is the usage of TableName instead of tableId directly. At the time of writing, in the attribute declaration, you can only use metadata assertion functions like tableStr(), classStr() and you cannot use the compile-time tableNum() function.

I have created following classes to test an attribute based child class construction. It simply constructs a child class per table Customer or Vendor and returns their name from the parmName method to test. The constructor of the base class was the code shown in the beginning, using a “switch” to construct the correct child class. After we implement attributes on our child classes, our construct is now changed to benefit from the SysExtensionAppClassFactory::getClassFromSysAttribute() method instead of using a switch statement:

public class AtTest{ protected Name name; protected Common common; public void initFromCommon(Common _common) { common = _common; } public Name parmName(Name _name = name) { name = _name; return name; } public static AtTest constructFromCommon(Common _common) { AtTest ret; AtTableNameAttribute tableNameAttribute = new AtTableNameAttribute(tableId2Name(_common.TableId)); ret = SysExtensionAppClassFactory::getClassFromSysAttribute(classStr(AtTest), tableNameAttribute); ret.initFromCommon(_common); return ret; }}[AtTableNameAttribute(tableStr(CustTable))]class AtTest_Customer extends AtTest{ public void initFromCommon(Common _common) { CustTable custTable = _common; super(_common); name =; }}[AtTableNameAttribute(tableStr(VendTable))]class AtTest_Vendor extends AtTest{ public void initFromCommon(Common _common) { VendTable vendTable = _common; super(_common); name =; }}Realize that we no longer have to modify the construct method of the base class. If we want to add another child class to AtTest class, we just create another child class and set the correct attribute on top of its declaration. One drawback is, at the time of writing, you cannot pass parameters to the new() method of the class if you construct it from the getClassFromSysAttribute() method. You have to construct the class itself without parameters and then pass parameters using initFrom__ or parm__ methods. So your older classes may need some re-construction as we did in our example here.

You can download the example code from the link below :

Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
sertandev: AX7 Extensibility Overview – Part 2 : Code extensions Blog bot DAX Blogs 0 28.08.2017 19:11
Navigate Into Success: State of .NET Affairs Blog bot NAV: Blogs 1 07.06.2017 11:03
atinkerersnotebook: Walkthrough & Tutorial Summary Blog bot DAX Blogs 1 09.09.2013 09:11
fed: Net requirements update in MRP Module and Working Set of MRP Blog bot DAX Blogs 14 08.05.2012 13:09
german_nav_developer: Codepage und Multilinguale Dynamics NAV Installationen Blog bot Dynamics CRM: Blogs 0 05.06.2011 15:51
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Часовой пояс GMT +3, время: 09:22.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.