Miklix

שימוש במסגרת SysExtension כדי לגלות איזו תת-מחלקה להפעיל ב- Dynamics AX 2012

פורסם: 16 בפברואר 2025 בשעה 0:26:15 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, לעתים קרובות אתה מתמודד עם יצירת היררכיית מחלקות שבה כל תת מחלקה מתאימה לערך enum או שיש לה צימוד נתונים אחר. עיצוב קלאסי הוא לאחר מכן לקבל שיטת בנייה ב- super class, שיש לה מתג שקובע איזו מחלקה להפעיל על סמך הקלט.

זה עובד היטב באופן עקרוני, אבל אם יש לך הרבה כניסות אפשריות ושונות (אלמנטים רבים ב-enum או אולי הקלט הוא שילוב של כמה ערכים שונים), זה יכול להיות מייגע ונוטה לשגיאות לתחזוקה ולעיצוב תמיד יש את החסרון שתצטרך לשנות את שיטת הבנייה האמורה אם אי פעם תוסיף תת-מחלקה חדשה או תבצע שינויים באיזו תת-מחלקה יש להשתמש בהתבסס על איזו קלט.

למרבה המזל, יש דרך הרבה יותר אלגנטית, אך למרבה הצער גם הרבה פחות מוכרת, לעשות זאת, כלומר באמצעות מסגרת SysExtension.

מסגרת זו מנצלת תכונות שבהן אתה יכול להשתמש כדי לקשט את מחלקות המשנה שלך כדי להפוך את המערכת מסוגלת להבין באיזו תת מחלקה יש להשתמש לטיפול במה. עדיין תזדקק לשיטת בנייה, אך אם תעשה זאת נכון, לעולם לא תצטרך לשנות אותה בעת הוספת מחלקות משנה חדשות.

בוא נסתכל על דוגמה דמיונית ונאמר שאתה הולך ליישם היררכיה שעושה איזשהו עיבוד המבוסס על טבלת InventTrans. איזה עיבוד לעשות תלוי ב-StatusReceipt וב-StatusIssue של הרשומות, כמו גם אם הרשומות קשורות ל-SalesLine, PurchLine או לאף אחת מהן. כבר עכשיו, אתה מסתכל על הרבה שילובים שונים.

אז נניח שאתה יודע שלעת עתה אתה צריך להתמודד רק עם קומץ מהשילובים, אבל אתה גם יודע שתתבקש להצליח להתמודד עם יותר ויותר שילובים עם הזמן.

בוא נשמור את זה פשוט יחסית ונאמר שלעת עתה אתה צריך לטפל רק ברשומות הקשורות ל-SalesLine עם StatusIssue של ReservPhysical או ReservOrdered, ניתן להתעלם מכל שאר השילובים לעת עתה, אבל מכיוון שאתה יודע שתצטרך לטפל בהם מאוחר יותר, תרצה לעצב את הקוד שלך בצורה שתאפשר להרחיב אותו בקלות.

ההיררכיה שלך עשויה להיראות בערך כך לעת עתה:

  • MyProcessor
    • MyProcessor_Sales
      • MyProcessor_Sales_Reserved
      • MyProcessor_Sales_ReservPhysical

כעת, אתה יכול בקלות ליישם שיטה במחלקת העל שמציגה תת-מחלקה המבוססת על ModuleInventPurchSales ו-StatusIssue enum. אבל אז תצטרך לשנות את מחלקת העל בכל פעם שתוסיף תת מחלקה, וזה לא באמת הרעיון של ירושה בתכנות מונחה עצמים. בסופו של דבר, אינך צריך לשנות את RunBaseBatch או 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. מה שהשיטה הזו עושה זה שהיא מקבלת את השם של מחלקת העל של היררכיה (ומחלקת העל הזו לא צריכה להיות בראש ההיררכיה; זה פשוט אומר שרק מחלקות שמרחיבות את המחלקה הזו יהיו כשירים) ואובייקט תכונה.

לאחר מכן הוא מחזיר אובייקט של מחלקה שמרחיב את מחלקת העל שצוינה ומעוטר בתכונה מתאימה.

ברור שאתה יכול להוסיף אימות או היגיון נוסף לשיטת הבנייה ככל שתרצה, אבל הנקודה החשובה כאן היא שברגע שהטמעה, לעולם לא תצטרך לשנות את השיטה הזו שוב. ניתן להוסיף מחלקות משנה להיררכיה וכל עוד מקפידים לקשט אותן כראוי, שיטת הבנייה תמצא אותן למרות שהן לא היו קיימות כשנכתבה.

מה לגבי ביצועים? למען האמת לא ניסיתי להשוות את זה, אבל תחושת הבטן שלי היא שכנראה זה מתפקד גרוע יותר מעיצוב הצהרת המתג הקלאסי. עם זאת, בהתחשב בכך שרוב בעיות הביצועים ב- Dynamics AX נגרמות מגישה לבסיס נתונים, לא הייתי דואג יותר מדי בקשר לזה.

כמובן, אם אתה מיישם משהו שיצריך ליצור במהירות אלפי אובייקטים, אולי תרצה לחקור יותר, אבל במקרים הקלאסיים שבהם אתה פשוט מיישם אובייקט בודד כדי לבצע עיבוד ממושך, אני בספק אם זה ישנה. כמו כן, בהתחשב בטיפ לפתרון הבעיות שלי (פסקה הבאה), נראה שמסגרת SysExtension מסתמכת על שמירה במטמון, כך שבמערכת פועלת אני בספק אם יש לה פגיעה משמעותית בביצועים.פתרון בעיות: אם שיטת הבנייה לא מוצאת את מחלקות המשנה שלך למרות שאתה בטוח שהן מעוטרות בצורה נכונה, ייתכן שזו בעיית מטמון. נסה לנקות מטמון גם בלקוח וגם בשרת. זה לא אמור להיות הכרחי להפעיל מחדש את ה-AOS, אבל זה עשוי להיות המוצא האחרון.

שתפו בבלוסקישתפו בפייסבוקשתפו בלינקדאיןשתפו ב-Tumblrשתפו ב-Xשתפו בלינקדאיןהצמד בפינטרסט

מיקל בנג כריסטנסן

על המחבר

מיקל בנג כריסטנסן
מיקל הוא היוצר והבעלים של miklix.com. יש לו למעלה מ-20 שנות ניסיון כמתכנת מחשבים/מפתח תוכנה מקצועי וכיום הוא מועסק במשרה מלאה בתאגיד IT אירופאי גדול. כשהוא לא כותב בלוג, הוא מבלה את זמנו הפנוי במגוון עצום של תחומי עניין, תחביבים ופעילויות, שעשויים לבוא לידי ביטוי במידה מסוימת במגוון הנושאים המכוסים באתר זה.