Miklix

Menggunakan Kerangka Kerja SysExtension untuk Menemukan Subkelas Mana yang Akan Dibuat Instansi di Dynamics AX 2012

Diterbitkan: 16 Februari 2025 pukul 00.25.45 UTC
Terakhir diperbarui: 12 Januari 2026 pukul 08.43.00 UTC

Artikel ini menjelaskan cara menggunakan kerangka kerja SysExtension yang kurang dikenal di Dynamics AX 2012 dan Dynamics 365 for Operations untuk membuat instance subkelas berdasarkan dekorasi atribut, sehingga memungkinkan desain hierarki kelas pemrosesan yang mudah diperluas.


Halaman ini diterjemahkan oleh mesin dari bahasa Inggris agar dapat diakses oleh sebanyak mungkin orang. Sayangnya, terjemahan mesin belum merupakan teknologi yang sempurna, sehingga kesalahan dapat terjadi. Jika Anda mau, Anda dapat melihat versi bahasa Inggris aslinya di sini:

Using the SysExtension Framework to Find Out Which Subclass to Instantiate in Dynamics AX 2012

Informasi dalam posting ini didasarkan pada Dynamics AX 2012 R3. Informasi ini mungkin berlaku atau mungkin tidak berlaku untuk versi lain. (Update: Saya dapat mengkonfirmasi bahwa informasi dalam artikel ini juga berlaku untuk Dynamics 365 for Operations)

Saat mengimplementasikan kelas pemrosesan di Dynamics AX, Anda sering dihadapkan pada pembuatan hierarki kelas di mana setiap subkelas sesuai dengan nilai enum atau memiliki beberapa keterkaitan data lainnya. Desain klasik adalah dengan memiliki metode konstruksi di kelas induk, yang memiliki pernyataan switch yang menentukan kelas mana yang akan diinstansiasi berdasarkan input.

Secara prinsip, ini berfungsi dengan baik, tetapi jika Anda memiliki banyak kemungkinan input yang berbeda (banyak elemen dalam enum atau mungkin inputnya merupakan kombinasi dari beberapa nilai yang berbeda), hal ini dapat menjadi membosankan dan rawan kesalahan untuk dipelihara, dan desain ini selalu memiliki kelemahan yaitu Anda perlu memodifikasi metode konstruksi tersebut jika Anda menambahkan subkelas baru atau membuat perubahan pada subkelas mana yang harus digunakan berdasarkan input mana.

Untungnya, ada cara yang jauh lebih elegan, tetapi sayangnya juga jauh kurang dikenal, untuk melakukan hal ini, yaitu dengan menggunakan kerangka kerja SysExtension.

Kerangka kerja ini memanfaatkan atribut yang dapat Anda gunakan untuk mendekorasi subkelas Anda agar sistem dapat menentukan subkelas mana yang harus digunakan untuk menangani apa. Anda tetap memerlukan metode konstruksi, tetapi jika dilakukan dengan benar, Anda tidak perlu memodifikasinya lagi saat menambahkan subkelas baru.

Mari kita lihat contoh imajiner dan katakanlah Anda akan mengimplementasikan hierarki yang melakukan beberapa jenis pemrosesan berdasarkan tabel InventTrans. Pemrosesan apa yang akan dilakukan bergantung pada StatusReceipt dan StatusIssue dari catatan, serta apakah catatan tersebut terkait dengan SalesLine, PurchLine, atau tidak keduanya. Saat ini, Anda sudah melihat banyak kombinasi yang berbeda.

Misalnya, Anda tahu bahwa untuk saat ini Anda hanya perlu menangani beberapa kombinasi saja, tetapi Anda juga tahu bahwa seiring waktu Anda akan diminta untuk dapat menangani lebih banyak kombinasi lagi.

Mari kita buat sesederhana mungkin dan katakan bahwa untuk saat ini Anda hanya perlu menangani catatan yang terkait dengan SalesLine dengan StatusIssue ReservPhysical atau ReservOrdered, semua kombinasi lain dapat diabaikan untuk saat ini, tetapi karena Anda tahu Anda harus menanganinya nanti, Anda perlu merancang kode Anda sedemikian rupa sehingga mudah diperluas.

Hierarki Anda mungkin akan terlihat seperti ini untuk saat ini:

  • MyProcessorMyProcessor_SalesMyProcessor_Sales_ReservedMyProcessor_Sales_ReservPhysical

Sekarang, Anda dapat dengan mudah mengimplementasikan metode di kelas induk yang membuat instance kelas turunan berdasarkan enum ModuleInventPurchSales dan StatusIssue. Tetapi Anda kemudian perlu memodifikasi kelas induk setiap kali Anda menambahkan kelas turunan, dan itu bukanlah ide pewarisan dalam pemrograman berorientasi objek. Lagipula, Anda tidak perlu memodifikasi RunBaseBatch atau SysOperationServiceBase setiap kali Anda menambahkan pekerjaan batch baru.

Sebagai gantinya, Anda dapat menggunakan kerangka kerja SysExtension. Ini akan mengharuskan Anda untuk menambahkan kelas lain, yang perlu memperluas SysAttribute. Kelas ini akan digunakan sebagai atribut yang dapat Anda gunakan untuk menghias kelas pemrosesan Anda.

Kelas ini sangat mirip dengan cara Anda membuat kelas kontrak data untuk implementasi SysOperation, karena akan memiliki beberapa anggota data dan metode parm untuk mendapatkan dan mengatur nilai-nilai tersebut.

Dalam kasus kita, ClassDeclaration mungkin terlihat seperti ini:

class MyProcessorSystemAttribute extends SysAttribute
{
    ModuleInventPurchSales  module;
    StatusIssue             statusIssue;
    StatusReceipt           statusReceipt
}

Anda perlu membuat metode `new()` untuk menginisialisasi semua anggota data. Jika Anda mau, Anda dapat memberikan nilai default pada sebagian atau seluruhnya, tetapi saya belum melakukannya.

public void new(ModuleInventPurchSales  _module,
                StatusIssue             _statusIssue,
                StatusReceipt           _statusReceipt)
{
    ;

    super();

    module          = _module;
    statusIssue     = _statusIssue;
    statusReceipt   = _statusReceipt;
}

Anda juga perlu mengimplementasikan metode parm untuk setiap anggota data, tetapi saya sengaja tidak menyertakannya di sini karena saya yakin Anda sudah tahu caranya - jika tidak, anggap saja ini sebagai latihan ;-)

Sekarang Anda dapat menggunakan kelas atribut Anda untuk mendekorasi setiap kelas pemrosesan Anda. Misalnya, deklarasi kelas dapat terlihat seperti ini:

[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
                            StatusIssue::None,
                            StatusReceipt::None)]
class MyProcessor_Sales extends MyProcessor
{
}

[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
                            StatusIssue::ReservOrdered,
                            StatusReceipt::None)]
class MyProcessor_Sales_ReservOrdered extends MyProcessor_Sales
{
}

[MyProcessorSystemAttribute(ModuleInventPurchSales::Sales,
                            StatusIssue::ReservPhysical,
                            StatusReceipt::None)]
class MyProcessor_Sales_ReservPhysical extends MyProcessor_Sales
{
}

Anda tentu saja dapat memberi nama kelas Anda sesuka hati, bagian penting di sini adalah Anda menambahkan atribut pada kelas Anda yang sesuai dengan jenis pemrosesan yang dilakukannya. (Namun perlu diingat bahwa ada konvensi penamaan untuk hierarki kelas di Dynamics AX dan selalu merupakan ide yang baik untuk mengikutinya, jika memungkinkan).

Setelah Anda mendekorasi kelas-kelas Anda untuk mengidentifikasi jenis pemrosesan yang dilakukan oleh masing-masing kelas, Anda dapat memanfaatkan kerangka kerja SysExtension untuk membuat instance objek dari subkelas sesuai kebutuhan.

Di kelas induk Anda (MyProcessor), Anda dapat menambahkan metode konstruksi seperti ini:

public static MyProcessor construct(ModuleInventPurchSales _module,
StatusIssue _statusIssue,
StatusReceipt _statusReceipt)
{
    MyProcessor                 ret;
    MyProcessorSystemAttribute  attribute;
    ;

    attribute = new MyProcessorSystemAttribute( _module,
                                                _statusIssue,
                                                _statusReceipt);

    ret = SysExtensionAppClassFactory::getClassFromSysAttribute(classStr(MyProcessor), attribute);

    if (!ret)
    {
        //  no class found
        //  here you could throw an error, instantiate a default
        //  processor instead, or just do nothing, up to you
    }

    return ret;
}

Bagian yang benar-benar menarik - dan sebenarnya tujuan (maaf atas permainan kata-kata ini) dari seluruh postingan ini - adalah metode getClassFromSysAttribute() di kelas SysExtensionAppClassFactory. Fungsi metode ini adalah menerima nama kelas induk dari sebuah hierarki (dan kelas induk ini tidak perlu berada di puncak hierarki; ini hanya berarti bahwa hanya kelas yang memperluas kelas ini yang memenuhi syarat) dan sebuah objek atribut.

Kemudian, fungsi ini mengembalikan objek dari kelas yang memperluas kelas induk yang ditentukan dan dihiasi dengan atribut yang sesuai.

Anda tentu saja dapat menambahkan validasi atau logika lebih lanjut sebanyak yang Anda inginkan ke metode konstruksi, tetapi poin penting di sini adalah bahwa setelah diimplementasikan, Anda seharusnya tidak perlu memodifikasi metode ini lagi. Anda dapat menambahkan subkelas ke hierarki dan selama Anda memastikan untuk mendekorasinya dengan tepat, metode konstruksi akan menemukannya meskipun subkelas tersebut belum ada saat metode tersebut ditulis.

Bagaimana dengan performanya? Sejujurnya saya belum mencoba melakukan benchmark, tetapi firasat saya mengatakan bahwa ini mungkin berkinerja lebih buruk daripada desain pernyataan switch klasik. Namun, mengingat bahwa sebagian besar masalah performa di Dynamics AX disebabkan oleh akses basis data, saya tidak akan terlalu khawatir tentang hal itu.

Tentu saja, jika Anda mengimplementasikan sesuatu yang membutuhkan pembuatan ribuan objek dengan cepat, Anda mungkin perlu menyelidiki lebih lanjut, tetapi dalam kasus klasik di mana Anda hanya membuat satu objek untuk melakukan pemrosesan yang memakan waktu lama, saya ragu itu akan berpengaruh. Selain itu, mengingat kiat pemecahan masalah saya (paragraf berikutnya), tampaknya kerangka kerja SysExtension bergantung pada caching, jadi dalam sistem yang sedang berjalan, saya ragu itu akan berdampak signifikan pada kinerja.

Penyelesaian Masalah: Jika metode konstruksi tidak menemukan subkelas Anda meskipun Anda yakin subkelas tersebut telah didekorasi dengan benar, mungkin ada masalah caching. Coba bersihkan cache di klien dan server. Seharusnya tidak perlu untuk benar-benar memulai ulang AOS, tetapi itu mungkin menjadi upaya terakhir.

Bacaan Lebih Lanjut

Jika Anda menikmati postingan ini, Anda mungkin juga menyukai saran berikut:


Bagikan di BlueskyBagikan di FacebookBagikan di LinkedInBagikan di TumblrBagikan di XBagikan di LinkedInPin di Pinterest

Mikkel Christensen

Tentang Penulis

Mikkel Christensen
Mikkel adalah pencipta dan pemilik miklix.com. Dia memiliki lebih dari 20 tahun pengalaman sebagai pemrogram komputer profesional/pengembang perangkat lunak dan saat ini bekerja penuh waktu di sebuah perusahaan IT besar di Eropa. Ketika tidak menulis blog, ia menghabiskan waktu luangnya untuk beragam minat, hobi, dan kegiatan, yang mungkin sampai batas tertentu tercermin dalam berbagai topik yang dibahas di situs web ini.