Miklix

Χρήση του πλαισίου SysExtension για να μάθετε ποια δευτερεύουσα κλάση για να ξεκινήσετε στο Dynamics AX 2012

Δημοσιεύθηκε: 16 Φεβρουαρίου 2025 στις 12:25:37 π.μ. UTC
Τελευταία ενημέρωση: 12 Ιανουαρίου 2026 στις 8:42:56 π.μ. UTC

Αυτό το άρθρο περιγράφει τον τρόπο χρήσης του λιγότερο γνωστού πλαισίου SysExtension στο Dynamics AX 2012 και το Dynamics 365 for Operations για τη δημιουργία υποκλάσεων με βάση τις διακοσμήσεις χαρακτηριστικών, επιτρέποντας μια εύκολα επεκτάσιμη σχεδίαση μιας ιεραρχίας κλάσεων επεξεργασίας.


Αυτή η σελίδα μεταφράστηκε μηχανικά από τα αγγλικά, προκειμένου να είναι προσβάσιμη σε όσο το δυνατόν περισσότερους ανθρώπους. Δυστυχώς, η αυτόματη μετάφραση δεν είναι ακόμη μια τελειοποιημένη τεχνολογία, οπότε μπορεί να προκύψουν λάθη. Αν προτιμάτε, μπορείτε να δείτε την πρωτότυπη αγγλική έκδοση εδώ:

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

Οι πληροφορίες σε αυτήν την ανάρτηση βασίζονται στο Dynamics AX 2012 R3. Ενδέχεται να ισχύουν ή όχι για άλλες εκδόσεις. (Ενημέρωση: Μπορώ να επιβεβαιώσω ότι οι πληροφορίες σε αυτό το άρθρο ισχύουν επίσης για το Dynamics 365 for Operations)

Κατά την υλοποίηση κλάσεων επεξεργασίας στο Dynamics AX, συχνά αντιμετωπίζετε τη δημιουργία μιας ιεραρχίας κλάσεων στην οποία κάθε υποκλάση αντιστοιχεί σε μια τιμή απαρίθμησης ή έχει κάποια άλλη σύζευξη δεδομένων. Ένας κλασικός σχεδιασμός είναι να υπάρχει στη συνέχεια μια μέθοδος κατασκευής στην υπερκλάση, η οποία έχει έναν διακόπτη που καθορίζει ποια κλάση θα δημιουργηθεί με βάση την είσοδο.

Αυτό λειτουργεί καλά κατ' αρχήν, αλλά αν έχετε πολλές διαφορετικές πιθανές εισόδους (πολλά στοιχεία σε μια απαρίθμηση ή ίσως η είσοδος είναι ένας συνδυασμός αρκετών διαφορετικών τιμών), η συντήρησή της μπορεί να γίνει κουραστική και επιρρεπής σε σφάλματα, και ο σχεδιασμός έχει πάντα το μειονέκτημα ότι θα χρειαστεί να τροποποιήσετε την εν λόγω μέθοδο κατασκευής εάν προσθέσετε ποτέ μια νέα υποκλάση ή κάνετε αλλαγές σε ποια υποκλάση θα πρέπει να χρησιμοποιηθεί με βάση ποια είσοδο.

Ευτυχώς, υπάρχει ένας πολύ πιο κομψός, αλλά δυστυχώς και πολύ λιγότερο γνωστός, τρόπος για να γίνει αυτό, δηλαδή με τη χρήση του πλαισίου SysExtension.

Αυτό το πλαίσιο αξιοποιεί τα χαρακτηριστικά που μπορείτε να χρησιμοποιήσετε για να διακοσμήσετε τις υποκλάσεις σας, ώστε το σύστημα να μπορεί να καταλάβει ποια υποκλάση πρέπει να χρησιμοποιηθεί για τον χειρισμό ποιας. Θα χρειαστείτε ακόμα μια μέθοδο κατασκευής, αλλά αν γίνει σωστά, δεν θα χρειαστεί ποτέ να την τροποποιήσετε κατά την προσθήκη νέων υποκλάσεων.

Ας δούμε ένα φανταστικό παράδειγμα και ας υποθέσουμε ότι πρόκειται να εφαρμόσετε μια ιεραρχία που εκτελεί κάποιο είδος επεξεργασίας με βάση τον πίνακα InventTrans. Η επεξεργασία που θα γίνει εξαρτάται από το StatusReceipt και το StatusIssue των εγγραφών, καθώς και από το αν οι εγγραφές σχετίζονται με το SalesLine, το PurchLine ή κανένα από τα δύο. Ήδη τώρα, εξετάζετε πολλούς διαφορετικούς συνδυασμούς.

Ας υποθέσουμε λοιπόν ότι γνωρίζετε ότι προς το παρόν χρειάζεται να χειριστείτε μόνο μερικούς από τους συνδυασμούς, αλλά γνωρίζετε επίσης ότι θα σας ζητηθεί να είστε σε θέση να χειριστείτε όλο και περισσότερους συνδυασμούς με την πάροδο του χρόνου.

Ας το κρατήσουμε σχετικά απλό και ας πούμε ότι προς το παρόν χρειάζεται να χειρίζεστε μόνο εγγραφές που σχετίζονται με το SalesLine με StatusIssue ReservPhysical ή ReservOrdered. Όλοι οι άλλοι συνδυασμοί μπορούν να αγνοηθούν προς το παρόν, αλλά επειδή γνωρίζετε ότι θα πρέπει να τους χειριστείτε αργότερα, θα πρέπει να σχεδιάσετε τον κώδικά σας με τρόπο που να τον καθιστά εύκολα επεκτάσιμο.

Η ιεραρχία σας μπορεί να μοιάζει κάπως έτσι προς το παρόν:

  • MyProcessorMyProcessor_SalesMyProcessor_Sales_ReservOrderedMyProcessor_Sales_ReservPhysical

Τώρα, θα μπορούσατε εύκολα να εφαρμόσετε μια μέθοδο στην υπερκλάση που δημιουργεί μια υποκλάση με βάση μια απαρίθμηση ModuleInventPurchSales και μια απαρίθμηση StatusIssue. Αλλά στη συνέχεια θα πρέπει να τροποποιείτε την υπερκλάση κάθε φορά που προσθέτετε μια υποκλάση, και αυτή δεν είναι στην πραγματικότητα η ιδέα της κληρονομικότητας στον αντικειμενοστρεφή προγραμματισμό. Άλλωστε, δεν χρειάζεται να τροποποιείτε το RunBatch ή το SysOperationServiceBase κάθε φορά που προσθέτετε μια νέα εργασία δέσμης.

Αντ' αυτού, μπορείτε να χρησιμοποιήσετε το πλαίσιο SysExtension. Αυτό θα απαιτήσει την προσθήκη μιας άλλης κλάσης, η οποία πρέπει να επεκτείνει το SysAttribute. Αυτή η κλάση θα χρησιμοποιηθεί ως το χαρακτηριστικό με το οποίο μπορείτε να διακοσμήσετε τις κλάσεις επεξεργασίας σας.

Αυτή η κλάση είναι πολύ παρόμοια με τον τρόπο που θα δημιουργούσατε μια κλάση σύμβασης δεδομένων για μια υλοποίηση SysOperation, καθώς θα έχει ορισμένα μέλη δεδομένων και μεθόδους parm για τη λήψη και τον ορισμό αυτών των τιμών.

Στην περίπτωσή μας, η ClassDeclaration μπορεί να μοιάζει κάπως έτσι:

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

Πρέπει να δημιουργήσετε μια μέθοδο new() για την δημιουργία στιγμιότυπων όλων των μελών δεδομένων. Αν θέλετε, μπορείτε να δώσετε σε ορισμένα ή σε όλα αυτά προεπιλεγμένες τιμές, αλλά δεν το έχω κάνει αυτό.

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

    super();

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

Και θα πρέπει επίσης να εφαρμόσετε μια μέθοδο parm για κάθε μέλος δεδομένων, αλλά τις έχω παραλείψει εδώ, καθώς είμαι σίγουρος ότι ξέρετε πώς να το κάνετε αυτό - διαφορετικά, ας το θεωρήσουμε άσκηση ;-)

Τώρα μπορείτε να χρησιμοποιήσετε την κλάση χαρακτηριστικών σας για να διακοσμήσετε κάθε μία από τις κλάσεις επεξεργασίας σας. Για παράδειγμα, οι δηλώσεις κλάσεων θα μπορούσαν να μοιάζουν με αυτό:

[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
{
}

Μπορείτε φυσικά να ονομάσετε τις κλάσεις σας με όποιον τρόπο θέλετε. Το σημαντικό εδώ είναι να διακοσμήσετε τις κλάσεις σας με χαρακτηριστικά που αντιστοιχούν στο είδος της επεξεργασίας που κάνουν. (Λάβετε όμως υπόψη ότι υπάρχουν συμβάσεις ονομασίας για τις ιεραρχίες κλάσεων στο Dynamics AX και είναι πάντα καλή ιδέα να τις ακολουθείτε, εάν είναι δυνατόν).

Τώρα που έχετε διακοσμήσει τις κλάσεις σας για να προσδιορίσετε το είδος της επεξεργασίας που κάνει η καθεμία από αυτές, μπορείτε να επωφεληθείτε από το πλαίσιο SysExtension για να δημιουργήσετε αντίγραφα αντικειμένων των υποκλάσεων, όπως απαιτείται.

Στην υπερκλάση σας (MyProcessor), θα μπορούσατε να προσθέσετε μια μέθοδο κατασκευής όπως αυτή:

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;
}

Το πραγματικά ενδιαφέρον μέρος - και στην πραγματικότητα το αντικείμενο (συγχωρήστε το λογοπαίγνιο) ολόκληρης αυτής της ανάρτησης - είναι η μέθοδος getClassFromSysAttribute() στην κλάση SysExtensionAppClassFactory. Αυτό που κάνει αυτή η μέθοδος είναι ότι δέχεται το όνομα της υπερκλάσης μιας ιεραρχίας (και αυτή η υπερκλάση δεν χρειάζεται να βρίσκεται στην κορυφή της ιεραρχίας. Αυτό σημαίνει απλώς ότι μόνο οι κλάσεις που επεκτείνουν αυτήν την κλάση θα είναι επιλέξιμες) και ένα αντικείμενο attribute.

Στη συνέχεια, επιστρέφει ένα αντικείμενο μιας κλάσης που επεκτείνει την καθορισμένη υπερκλάση και διακοσμείται με ένα αντίστοιχο χαρακτηριστικό.

Μπορείτε προφανώς να προσθέσετε όση περαιτέρω επικύρωση ή λογική θέλετε στη μέθοδο κατασκευής, αλλά το σημαντικό συμπέρασμα εδώ είναι ότι μόλις εφαρμοστεί, δεν θα χρειαστεί ποτέ ξανά να τροποποιήσετε αυτήν τη μέθοδο. Μπορείτε να προσθέσετε υποκλάσεις στην ιεραρχία και εφόσον βεβαιωθείτε ότι τις διακοσμείτε κατάλληλα, η μέθοδος κατασκευής θα τις βρει ακόμα κι αν δεν υπήρχαν όταν γράφτηκε.

Τι γίνεται με την απόδοση; Ειλικρινά, δεν έχω επιχειρήσει να τη συγκρίνω, αλλά η διαίσθησή μου είναι ότι πιθανότατα έχει χειρότερη απόδοση από τον κλασικό σχεδιασμό δήλωσης διακόπτη. Ωστόσο, λαμβάνοντας υπόψη ότι τα περισσότερα προβλήματα απόδοσης στο Dynamics AX προκαλούνται από την πρόσβαση σε βάσεις δεδομένων, δεν θα ανησυχούσα πολύ για αυτό.

Φυσικά, αν υλοποιείτε κάτι που θα απαιτήσει τη γρήγορη δημιουργία χιλιάδων αντικειμένων, ίσως θελήσετε να το διερευνήσετε περαιτέρω, αλλά στις κλασικές περιπτώσεις όπου απλώς δημιουργείτε ένα μόνο αντικείμενο για να κάνετε κάποια μακρά επεξεργασία, αμφιβάλλω αν θα έχει σημασία. Επίσης, λαμβάνοντας υπόψη την συμβουλή αντιμετώπισης προβλημάτων (επόμενη παράγραφος), φαίνεται ότι το πλαίσιο SysExtension βασίζεται στην προσωρινή αποθήκευση, επομένως σε ένα σύστημα που εκτελείται αμφιβάλλω αν έχει σημαντική μείωση στην απόδοση.

Αντιμετώπιση προβλημάτων: Εάν η μέθοδος κατασκευής δεν εντοπίσει τις υποκλάσεις σας παρόλο που είστε βέβαιοι ότι έχουν διακοσμηθεί σωστά, ενδέχεται να πρόκειται για πρόβλημα προσωρινής αποθήκευσης. Δοκιμάστε να καθαρίσετε τις προσωρινές μνήμες τόσο στον πελάτη όσο και στον διακομιστή. Δεν θα πρέπει να είναι απαραίτητο να επανεκκινήσετε το AOS, αλλά μπορεί να είναι η έσχατη λύση.

Περαιτέρω ανάγνωση

Αν σας άρεσε αυτή η ανάρτηση, ίσως σας αρέσουν και αυτές οι προτάσεις:


Μοιραστείτε το στο BlueskyΚοινή χρήση στο FacebookΚοινοποίηση στο LinkedInΜοιραστείτε το στο TumblrΚοινοποίηση στο XΚοινοποίηση στο LinkedInΚαρφιτσώστε στο Pinterest

Mikkel Christensen

Σχετικά με τον συγγραφέα

Mikkel Christensen
Ο Μιχαήλ είναι ο δημιουργός και ιδιοκτήτης του miklix.com. Έχει πάνω από 20 χρόνια εμπειρίας ως επαγγελματίας προγραμματιστής υπολογιστών/προγραμματιστής λογισμικού και σήμερα εργάζεται με πλήρη απασχόληση σε μια μεγάλη ευρωπαϊκή εταιρεία πληροφορικής. Όταν δεν ασχολείται με το ιστολόγιο, αφιερώνει τον ελεύθερο χρόνο του σε ένα ευρύ φάσμα ενδιαφερόντων, χόμπι και δραστηριοτήτων, τα οποία μπορεί σε κάποιο βαθμό να αντικατοπτρίζονται στην ποικιλία των θεμάτων που καλύπτονται σε αυτόν τον ιστότοπο.