צ'קליסט לפני migration מ-.NET Framework ל-.NET

· עודכן בתאריך: · · .NET, .NET Framework, C#, modernization, פיתוח Windows, migration

היסטוריית עדכונים (גרסה ראשונה, פורסמה בתאריך 15 Mar 2026)
פרסום ראשון
לצטט את המאמר הזה(DOI: 10.5281/zenodo.22173485)

מאמר זה מאוחסן בארכיון Zenodo. להלן גם ה-DOI שתמיד מפנה לגרסה האחרונה וגם ה-DOI המקובע לגרסה שאתם קוראים.

Go Komura (2026). צ'קליסט לפני migration מ-.NET Framework ל-.NET. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22173485 https://comcomponent.com/he/blog/dotnet-framework-to-dotnet-premigration-checklist/

DOI (הגרסה האחרונה)
10.5281/zenodo.22173485
DOI (הגרסה הזו)
10.5281/zenodo.22173486

הורידו את הצ’קליסט ב-Excel עם גיליון יפני ואנגלי

הקובץ הזה בנוי משני גיליונות, Checklist-ja ו-Checklist-en, ומוריד את צ’קליסט 13 הפרקים שלפני תחילת העבודה ל-7 קטגוריות ו-34 סעיפים: מדיניות / הכנת צד .NET Framework הנוכחי / סוג האפליקציה ובחירת טכנולוגיה / טכנולוגיות לא נתמכות ו-API-ים שדורשים תשומת לב / תלות Windows-only / shared library וגישה לנתונים / תפעול ו-build. עמודות Status ו-Notes נשארות ריקות, כך שאפשר להשתמש בקובץ ישירות כטבלת inventory לכל פרויקט. כדאי לעבור עליו לפני קריאת המאמר — כך קל יותר לתפוס את הזרימה עד פרק 13.

משנים את TargetFramework ב-.csproj ל-net10.0, מעדכנים כמה חבילות NuGet, וכש-build עובר — סיימנו.

……אם זה היה ה-migration, זה היה די שליו. בפועל, בדרך כלל זה לא ככה.

בסביבת .NET Framework בשטח יש לא מעט הנחות שבדרך כלל לא שמים לב אליהן: System.Web, WCF, Web Forms, packages.config ישן, web.config.install.xdt, native DLL, COM / ActiveX, בקרות צד שלישי שרצות רק ב-design-time, הנחה שקטה של x86, ResX שתלוי ב-designer, ו-serializer ישן.

לכן, מה שבאמת חשוב ב-migration מ-.NET Framework ל-.NET הוא ה-inventory לפני שמתחילים לממש. אם מפרקים את הסוגיות לפני שמתחילים, ה-migration נהיה לא “הימור גדול” אלא “עבודה שסוגרים סעיף אחרי סעיף”.

inventory משנה את אופי ה-migrationאם עושים inventory לפני שמתחילים לממש ומפרקים את הסוגיות, ה-migration נהיה עבודה לפי סדר. דילוג על ה-inventory הופך אותו להימור גדול.אם מדלגים על ה-inventoryהנחות סמויות ישנותinventory לפני שמתחילים מפרק סוגיותעבודה שסוגרים סעיף אחרי סעיףה-migration הופך להימור גדול

איור 1: היכולת לפרק סוגיות לפני שמתחילים קובעת אם ה-migration יהיה הימור או עבודה מסודרת.

המאמר הזה מסכם מה כדאי לבדוק לפני שמעבירים אפליקציה עסקית קיימת ב-.NET Framework 4.x ל-.NET הנוכחי. היעד העיקרי הוא סוגי האפליקציות הבאים:

  • class library
  • console
  • Windows Service
  • WinForms / WPF
  • ASP.NET Framework (MVC / Web API / Web Forms)
  • אפליקציות שמשתמשות ב-WCF
  • אפליקציות שמשתמשות ב-EF6

זמן הכתיבה הוא 2026-03-15. תקופות התמיכה והמלצות הכלים הרשמיים משתנות, ולכן אם קוראים את המאמר בפער זמן, כדאי לבדוק גם את המידע הרשמי.

1. קודם המסקנות

תחילה, רק את המסקנות שלא כדאי לפספס:

  • קודם מכינים את צד .NET Framework לפני ה-migration. גם במדריך הרשמי של Microsoft ממליצים, לפני ה-port, לעלות ל-.NET Framework 4.7.2 ומעלה, להמיר ל-PackageReference, לעבור ל-SDK-style, ולעדכן תלויות קודם.
  • הקושי נקבע לפי app model, לא לפי כמות הקוד. class library ו-console יחסית קלים, ואילו ASP.NET Framework, Web Forms, WCF server ו-WF (Workflow Foundation) נוטים להיות כבדים.
  • WinForms / WPF יכולים לעבור ל-.NET אבל נשארים Windows-only. טעות בהבנה כאן מובילה למוקש קלאסי — עשיתם migration ועדיין לא רצים על Linux container.
  • המעבר מ-ASP.NET Framework ל-ASP.NET Core הוא בפועל מעבר ארכיטקטורה. באפליקציה קטנה אפשר לפעמים לעבור בבת אחת, אבל במערכת production גדולה בטוח יותר להניח incremental migration.
  • WCF ו-EF6 לפעמים אפשר להפריד מ-migration של ה-runtime. ל-WCF client יש חבילה נתמכת ל-.NET, ו-EF6 אפשר להעביר בנפרד ל-EF Core אחרי המעבר ל-modern .NET.
  • מצד שני, יצירת AppDomain, .NET Remoting, CAS (Code Access Security), COM+, Workflow Foundation, ותלות ב-BinaryFormatter הם red flags. אם לא מוצאים אותם קודם, נפח העבודה מתפוצץ בהמשך.
  • packages.config / install.ps1 / XDT (XML Document Transform, מנגנון שהופך web.config וכדומה) / נכסי content / native DLL / COM / ActiveX / הנחת x86 — כל אלה נוטים ליפול ב-runtime או ב-design-time גם כש-build עובר, ולכן סורקים אותם לפני שמתחילים.
  • נכון ל-2026-03, .NET 10 הוא LTS. נקודת היעד ל-migration חדש טבעי לחשוב עליה בהתבסס על ה-LTS הנוכחי.
  • migration בלי בדיקות, מדידה והכנה ל-rollback הוא מסוכן. ה-migration הוא לא בעצם עבודת מימוש, אלא עבודה של חשיפת תנאי היסוד אחד-אחד.

ב-diagram, solid line מציינת relation שתמיד מתקיים ו-dashed line מציינת relation מותנה (התנאים מופיעים בהסבר של כל relation ב-detail page). הרשימה המלאה של ה-relations (סה”כ 30, כולל evidence ו-certainty) וההגדרות של ה-concepts המרכזיים נמצאות ב-detail page של ה-knowledge map (ביפנית). Data: JSON-LD / Turtle

2. קודם קובעים אם באמת צריך לעבור עכשיו

הדבר הראשון שכדאי לקבוע הוא לא “איך עושים migration”, אלא האם באמת צריך להעביר את האפליקציה הזו עכשיו.

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

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

איור 2: בלי לקבוע “האם צריך לעבור עכשיו” לפני “איך”, ההחלטה נוטה להיסחף לכיוון אחד.

2.1 גם החלטה להישאר על .NET Framework היא סבירה לגמרי

.NET Framework 4.8.1 ממשיך לקבל תמיכה כל עוד הוא רץ על Windows נתמך. כלומר, זה לא סיפור פשוט של “אם לא נעביר הכול מיד ל-modern .NET, זה מסוכן”.

עם זאת, להישארות יש מגבלות ברורות.

  • אי אפשר לצאת מ-Windows-only
  • ממשיכים לשאת ASP.NET Web Forms או שכבת שרת ישנה
  • קשה ליהנות משיפורי ביצועים, תכונות שפה ואקוסיסטם של .NET חדש
  • קל להיסחף מהנחות עדכניות של cloud, container ו-CI/CD

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

הישארות היא בחירה סבירהאם יש תלות legacy חזקה כמו Web Forms, תאימות WCF server או COM+, הגיוני להישאר בינתיים על .NET Framework 4.8.1 עם תפעול יציב, ולתכנן החלפה בקו נפרד.יש תלות legacy חזקהבינתיים, תפעול יציב על 4.8.1תכנון החלפה בקו נפרדמגבלות כמו Windows-only נשארות

איור 3: כשהתלות עמוקה, שילוב של תפעול יציב על 4.8.1 ותכנון החלפה נפרד הוא ריאלי.

  • יש כמות גדולה של מסכי Web Forms
  • צריך לשמור בקפדנות על תאימות WCF server
  • תלות עמוקה ב-Workflow Foundation או ב-COM+
  • רכיב design-time של צד שלישי לא נתמך ב-modern .NET
  • לא ניתן לאשר עסקית שינוי אפיון גדול

2.2 מה משתנה לפי כל בחירה

בחירה מה משתפר מה נשאר / מה נאבד מתי מתאים
להישאר על .NET Framework 4.8.1 קל יותר לשמור על נכסים קיימים ולתפעל ביציבות Windows-only, app model ישן, מגבלת modernization תלות legacy חזקה, כרגע עדיפות עסקית עם תפעול יציב
migration ל-modern .NET, נשארים ב-Windows אפשר להביא runtime ו-toolchain מודרניים. תועלת גדולה בביצועים, חוויית פיתוח ו-SDK-style תלות ב-Windows API נשארת. לא הופך ל-cross-platform אפליקציה עסקית שמשתמשת ב-WinForms / WPF, Windows Service, Windows API
migration ל-modern .NET, עם ראייה לעתיד ל-Linux / container / cloud חופש רב יותר ב-deployment. קל יותר גם לחדש את מודל התפעול צריך להסיר קודם API-ים ו-app model ייעודיים ל-Windows רוצים להעביר את צד השרת ל-cloud, וגם לחדש את התשתית

חשוב לקבוע קודם לא האם רוצים לעשות migration, אלא לאן רוצים להגיע אחריו.

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

איור 4: אם משנים את השאלה מ”רוצים לעבור?” ל”לאן רוצים להגיע?”, האפשרויות מתבררות.

3. ארבע מדיניות שכדאי לקבוע מראש

3.1 גרסת .NET של נקודת היעד

בזמן הכתיבה, לפי מדיניות התמיכה של Microsoft, .NET 10 הוא LTS. מצד שני, .NET 8 LTS ו-.NET 9 STS שניהם מתוכננים לסיים תמיכה באותו התאריך, 2026-11-10. הסיבה ש-STS מקבל את אותו תאריך כמו LTS היא שתקופת ה-STS הוארכה מ-18 חודשים ל-24 חודשים. אם סופרים לפי ההנחה הישנה ש”STS זה 18 חודשים”, נראה שסיום התמיכה של .NET 9 הוא ב-2026-05-12, ולכן כשמתבססים על תאריך, כדאי לוודא מול מידע מחזור החיים הרשמי.

לכן, כשעוברים מ-.NET Framework מחדש, אלא אם יש נסיבות מיוחדות, טבעי לקבוע את ה-LTS הנוכחי כנקודת היעד.

הגישה המעשית כאן פשוטה:

  • לmigration קטן שרוצים לסיים מהר, מגיעים ישירות ל-LTS הנוכחי
  • גם במערכת ליבה עם תפעול ארוך-טווח, חושבים ראשית על ה-LTS הנוכחי
  • “בגלל נוחות ספרייה קיימת רוצים LTS קודם” יכול להיות נסיבה סבירה, אבל בודקים עד מתי היא נתמכת לפי תאריך
הגישה לבחירת גרסת היעדגם migration קטן וגם מערכת ליבה בוחרים בבסיס ב-LTS הנוכחי. אם רוצים LTS קודם בגלל ספרייה קיימת, בודקים את תאריך סיום התמיכה.בסיסנוחות ספרייה קיימתבוחרים .NET לנקודת היעדמגיעים ל-LTS הנוכחישוקלים גם LTS קודםבודקים תאריך סיום תמיכה ומחליטים

איור 5: נקודת היעד הבסיסית היא ה-LTS הנוכחי, ואם בוחרים ב-LTS ישן, מבססים על תאריך תפוגת התמיכה.

3.2 להישאר Windows-only, או לשאוף ל-cross-platform בעתיד

ההחלטה הזו משנה משמעותית מה בודקים.

  • אם נשארים Windows-only, אפשר לנקוט מסלול מעשי של modernization קודם ל-runtime, בעזרת WPF / WinForms ו-Windows Compatibility Pack.
  • אם שואפים בעתיד גם ל-Linux / containerization, צריך לעשות inventory מוקדם ל-API-ים שמניחים Windows כמו System.Drawing.Common, Registry, WMI, EventLog, Windows Service ו-Office Interop.

אם לא מחליטים על זה ומתחילים migration, בהמשך הדיון מתפתל לכיוון “האם באמת נכון היה להישאר על Windows” או “לא, רצינו לשים על container”.

ההסתעפות בין Windows-only ל-cross-platformאם נשארים Windows-only אפשר לנקוט מסלול מעשי של modernization ל-runtime עם Windows Compatibility Pack. אם שואפים בעתיד ל-container או ל-Linux, צריך inventory מוקדם של API-ים שמניחים Windows.נשארים Windows-onlyבעתיד גם containerמתחילים בלי להחליטבאיזה כיוון שואפיםmodernization של runtime עם Windows Compatibility Packinventory מוקדם של API-ים שמניחים Windowsהדיון מתפתל באמצע

איור 6: בלי להחליט על ההסתעפות הזו מראש, מה שצריך לבדוק לא מתברר, והדיון מתפתל באמצע.

3.3 לעשות הכול בבת אחת, או incremental migration

יש שלושה סוגים עיקריים ל-migration:

  • migration מרוכז שקרוב ל-in-place
  • migration שבו ישן וחדש רצים side-by-side זה לצד זה
  • incremental migration שמתקדם בהדרגה לפי route / library

בפרט, באפליקציות ASP.NET Framework, גם המדריך של Microsoft מנחה בבירור ל-incremental migration. אם לא רוצים לעצור את ה-production, יש הרבה תכונות, והתלויות סביב רבות, טבעי יותר לתכנן מראש מתוך הנחת incremental migration.

שלושת הסוגים של ה-migrationיש שלושה סוגי migration: מרוכז קרוב ל-in-place, side-by-side עם ישן וחדש במקביל, ו-incremental לפי route או library. בתנאי שלא רוצים לעצור production, ההדרגתי טבעי יותר.בוחרים סוג migrationmigration מרוכז (קרוב ל-in-place)side-by-side עם ישן וחדש במקבילincremental לפי route / libraryאם לא רוצים לעצור production, זו ההנחה הטבעית

איור 7: יש שלושה סוגי migration, ובמערכת production עם הרבה תכונות שלא ניתן לעצור, incremental הוא ההנחה הטבעית.

3.4 מה מוציאים מהיקף ה-migration הזה

migration נוטה להיכשל כי לוקחים על עצמם יותר מדי.

לדוגמה, לעשות בו-זמנית את הבאים נוטה להיות כבד:

  • .NET Framework → .NET
  • ASP.NET Framework → ASP.NET Core
  • EF6 → EF Core
  • Windows Server → Linux container
  • שינוי תשתית authentication
  • שינוי תשתית logs / monitoring
  • migration של database

כמובן שכולם עשויים להידרש בשלב כלשהו. אבל האם צריך לעשות אותם בו-זמנית זה עניין אחר.

בפועל, ההפרדה הבאה עובדת יותר טוב:

  1. קודם, modernization של runtime ומבנה הפרויקט
  2. על גביה, העברת app model
  3. לבסוף, עדכון ORM, authentication, cloud ו-monitoring
סדר ההפרדה שלא לוקחים יותר מדיקודם עושים modernization ל-runtime ולמבנה, אחר כך מעבירים את ה-app model, ולבסוף מעדכנים ORM, authentication, cloud ו-monitoring. סדר הפרדה שמונע מה-migration להיות כבד.אם לוקחים הכול בו-זמניתmodernization של runtime ומבנההעברת app modelעדכון ORM, authentication, cloud ו-monitoringה-migration נהיה כבד ונוטה להיכשל

איור 8: בלי לעשות הכול בו-זמנית, אלא בהפרדה של runtime, app model והשוליים, ה-migration לא נהיה כבד.

4. הבסיס שמכינים לפני שמתחילים

המדריך המקדים ל-port של Microsoft מעשי מאוד. בקיצור, מדובר בהכנת פרויקט .NET Framework הנוכחי לכיוון כניסה מודרנית לפני ה-migration.

4.1 עלייה ל-.NET Framework 4.7.2 ומעלה

במדריך הרשמי מומלץ, לפני ה-port, לכוון ל-.NET Framework 4.7.2 ומעלה. הסיבה היא שגם כש-.NET Standard לא מחזיק ישירות את ה-API הקיים, קל יותר להתקרב לחלופת API עדכנית יותר.

בשטח, אם אפשר, ברור יותר לחשוב מנקודת מוצא של 4.8.1.

  • ברור יותר מבחינת נקודת מבט התמיכה
  • קל יותר להתייחס לזה כנקודת יציבות אחרונה בצד .NET Framework
  • קל יותר לגבש מדיניות של “קודם מכינים בצד ה-Framework הנוכחי”

מה משתנה אם עושים את זה קודם

  • קל יותר לייצב את הטיפול ב-shared library של .NET Standard 2.0
  • אפשר לצמצם מראש רעש שמקורו ב-runtime ישן
  • קל יותר להפריד אם בעיית תאימות מגיעה מ-Framework ישן או מהמעבר ל-modern .NET

4.2 מעבר ל-PackageReference

במדריך המקדים מומלץ להתקדם צורת ההפניה ל-PackageReference. אם עושים את זה קודם, התצוגה הכוללת של ניהול התלויות משתפרת משמעותית.

מה משתנה כשעוברים ל-PackageReference

  • הפניות החבילות מרוכזות ב-csproj
  • קל יותר לראות תלויות טרנזיטיביות
  • הנחת ה-restore מתאימה לצד modern .NET
  • תאימות טובה יותר עם CLI / CI

עם זאת, יש כאן נקודה שנופלים בה.

ה-gotcha הטיפוסי

בתיעוד הרשמי של NuGet כתובות המגבלות הבאות במעבר מ-packages.config ל-PackageReference:

  • פונקציית ההמרה המובנית של Visual Studio לא זמינה בפרויקטי ASP.NET
  • חבילות שתלויות ב-install.ps1 / uninstall.ps1 עלולות לא לפעול כצפוי
  • נכסים בתיקיית content עלולים להיות מתעלמים
  • המרות XDT כמו web.config.install.xdt לא מוחלות
  • חבילות עם מבנה assembly ישן תחת lib עלולות לא להסתדר כראוי

כלומר, לא כדאי לחשוב שמדובר רק בשינוי צורת החבילה. בפרט, ל-classic ASP.NET הייתה תרבות משמעותית שבה התקנת חבילת NuGet כותבת מחדש את web.config, ולכן בזמן ה-migration קל שהנחות סמויות יעלו לפני השטח.

הנחות סמויות שנחשפות במעבר ל-PackageReferenceבמעבר מ-packages.config ל-PackageReference, install.ps1 והמרות XDT ונכסי content עלולים לא להיות מוחלים, ולכן הנחות סמויות שהתבססו על כתיבה מחדש של web.config בזמן התקנה נחשפות.המרה ל-PackageReferenceinstall.ps1 עלול לא לפעולהמרות XDT לא מוחלותנכסי content עלולים להתעלםההנחות הסמויות נחשפות

איור 9: גם אם חושבים שזו רק המרת צורה, ההסתמכות על מנגנוני ההתקנה נחשפת בבת אחת.

באילו כלים ממירים

זה לא רק עבודה ידנית. עם זאת, לכל כלי טווח שונה.

כלי מה אפשר לעשות הנחות והערות
פונקציית ההמרה של Visual Studio ב-Solution Explorer, לחיצה ימנית על “References” או על packages.config ובחירה ב-Migrate packages.config to PackageReference... מבצעת המרה Visual Studio 2017 15.7 ומעלה. לא זמין בפרויקטי ASP.NET ו-C++. אם לא מופיע בתפריט, פותחים פעם את NuGet restore או את Package Manager ואז לוחצים ימנית שוב
.NET Upgrade Assistant מבצע ניתוח ושדרוג של הפרויקט יחד בתיעוד הרשמי הוא כבר לא מומלץ, ומופנים להשתמש ב-GitHub Copilot app modernization
GitHub Copilot app modernization מסייע עד להערכה, תכנון, תיקון קוד ואימות ליבת ההנחיה הרשמית הנוכחית. כפי שבפרק 4.5, מניח Visual Studio, Copilot וקוד C#
המרה ידנית ל-SDK-style יוצרים csproj חדש ומעבירים רק את הפריטים הנדרשים בפרויקט עם מעט קבצים, לעיתים זה המהיר ביותר

פונקציית ההמרה של Visual Studio יוצרת גיבוי של הפרויקט לפני ההרצה, ומוציאה בסוף דוח המרה (תלויות ברמה עליונה, תלויות טרנזיטיביות, בעיות תאימות שזוהו). בתיעוד כתוב שאם רוצים לחזור אחורה, משחזרים את csproj ואת packages.config מתיקיית הגיבוי, ומריצים update-package -reinstall ב-Package Manager Console.

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

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

איור 10: ההמרה ניתנת לניסיון עם גיבוי ודוח, ולכן קודם בודקים על פרויקט אחד.

4.3 מעבר ל-SDK-style

במדריך המקדים מומלצת גם המרה לצורת פרויקט SDK-style.

זה משפיע משמעותית.

מה משתנה עם SDK-style

  • ה-csproj נעשה פשוט משמעותית
  • תאימות טובה עם PackageReference
  • קל יותר לבצע multi-targeting
  • קל יותר להתאים ל-CI/CD שמתבסס על dotnet build / dotnet test / dotnet publish
  • הקרבה למבנה של צד modern .NET מצמצמת את ה-gap בשלב השני

מנקודת מבט הפוכה, זה אומר שאם קופצים ישר ל-modern .NET עם csproj ישן וניהול NuGet ישן, ה-gap גדול מדי.

מעבר ל-SDK-style מצמצם gapקפיצה ישירה ל-modern .NET עם csproj ישן וניהול NuGet ישן יוצרת gap גדול מדי. מעבר קודם ל-SDK-style מקרב למבנה הצד המודרני ומצמצם את ה-gap בהמשך.קפיצה ישירהקודם מעבר ל-SDK-stylecsproj ישן + ניהול NuGet ישןgap גדול מדיהתקרבות למבנה הצד המודרניה-gap בהמשך מצטמצם

איור 11: אם משלבים מעבר ל-SDK-style, ה-gap בקפיצה ל-modern .NET מצטמצם.

4.4 עדכון תלויות קודם

גם זה לפי המדריך הרשמי, אבל את התלויות מקדמים להגרסה העדכנית הזמינה, ואם אפשר, לגרסה שתומכת ב-.NET Standard.

המשמעות בעשיית זה קודם

  • מהר יותר יודעים “האם אפשר להשתמש בחבילה הזו ב-modern .NET”
  • מונעים מתלויות ישנות להפוך לרעש
  • קל יותר להמיר shared library ל-netstandard2.0
  • קל יותר לרכז את עבודת ה-migration בשלב הבא ב”העברת הקוד”
המשמעות בעדכון התלויות קודםעדכון התלויות מראש לגרסה עדכנית מאפשר לדעת מהר אם הן תומכות ב-modern .NET, מפחית רעש מתלויות ישנות, ומאפשר לרכז את עבודת ה-migration בשלב הבא בהעברת הקוד.עדכון התלויות מראשמהר יותר יודעים אם תומך ב-modern .NETמפחית רעש מתלויות ישנותהשלב הבא מתמקד בהעברת הקוד

איור 12: ככל שעדכון התלויות מוקדם יותר, גוף ה-migration יכול להתמקד בהעברה עצמה.

4.5 בודקים גם את הנחות הכלים הרשמיים

נכון ל-2026-03, מרכז הכובד של הנחיית Microsoft עבר לכיוון GitHub Copilot app modernization. במקום להתבסס רק על כלי migration ותיקים, מעשי יותר להתייחס לזה כזרם תמיכה שכולל הערכה, תכנון, תיקון קוד ואימות.

עם זאת, בתיעוד הנוכחי, ההנחה היא Visual Studio 2026 או Visual Studio 2022 בגרסה נתמכת, GitHub Copilot, וגם קוד C#.

למה הבדיקה הזו נדרשת

  • מה אפשר לצפות מהכלי הרשמי משתנה
  • קל יותר להתאים בין הצוות את הנחות ה-IDE / build agent / התוספים
  • אפשר להגיע להחלטה שלא לצפות ליותר מדי אוטומציה ב-solution-ים של VB.NET

לא נדיר לראות סביבת עבודה שיש בה גם VB.NET. לכן, שווה לבדוק מראש “עד כמה הכלי הרשמי העדכני יעזור”.

המצב הנוכחי וההנחות של הכלים הרשמיים.NET Upgrade Assistant נהיה לא מומלץ ומרכז הכובד של ההנחיה עבר ל-GitHub Copilot app modernization, אבל ההנחה היא Visual Studio, Copilot וקוד C#, ולכן בסביבה עם VB.NET לא כדאי לצפות ליותר מדי אוטומציה.לא מומלץ, מפנה לאם יש VB.NET.NET Upgrade AssistantGitHub Copilot app modernizationהנחה: Visual Studio + Copilot + C#לא לצפות ליותר מדי אוטומציה

איור 13: מרכז הכובד של הכלים עבר ל-Copilot app modernization, וסביבה שלא תואמת את ההנחות שלו דורשת התייחסות נפרדת.

5. אומדים את הקושי לפי סוג הפרויקט

נוטים לדבר על ה-migration מ-.NET Framework ל-.NET כעל דבר אחד, אבל בפועל כל סוג פרויקט הוא משחק בפני עצמו.

5.1 תחושת קושי גסה

סוג תחושת קושי הנקודות המרכזיות
class library נמוך~בינוני תאימות API, תלויות, חלוקת target
console / batch / חלק מ-Windows Service נמוך~בינוני שיטת הפצה, תלות native, תצורה
WinForms / WPF בינוני נשאר Windows-only, designer, UI צד שלישי, סביבת BinaryFormatter
ASP.NET MVC / Web API בינוני~גבוה מעבר app model ל-ASP.NET Core, authentication, session, תצורה, DI
ASP.NET Web Forms גבוה הפרש גדול במודל המסך, הנחת החלפת שכבת UI
WCF client בינוני החלפת חבילה, חוזה, תצורה
WCF server גבוה CoreWCF או תכנון מחדש עם gRPC / HTTP API
ביצוע בו-זמני של EF6 → EF Core גבוה ORM שונה לגמרי, הבדל התנהגות, היסטוריית migration

5.2 המפתח ב-class library הוא איך חותכים את הגבול המשותף

class library יחסית קלה להעברה. עם זאת, זה נכון רק כשהספרייה באמת מופרדת כמו ספרייה.

תלויות מהסוג הבא מעלות את הקושי:

  • נוגעים ב-System.Web
  • מסתכלים ישירות ב-HttpContext.Current
  • כוללים טיפוסי WPF / WinForms ב-API הציבורי
  • נשענים יתר על המידה על Windows API כמו Registry, WMI, EventLog
  • תלויים ב-AppDomain או ב-Remoting

אם אפשר להוציא רק business logic, זה קל, ואם נושאים גם את ה-app model, זה כבד — כך קל יותר להבין.

איך רואים את כובד ה-class libraryספרייה שבה אפשר להוציא רק business logic קלה ל-migration, ואילו ספרייה שנושאת גם app model דרך System.Web, טיפוסי UI, Windows API ו-AppDomain כבדה.אפשר להוציא רק לוגיקהנושאת app modelבוחנים class librarymigration קלmigration כבדתלות ב-System.Web, טיפוסי UI, Windows API וכדומה

איור 14: הקושי של הספרייה נקבע לא לפי מספר השורות, אלא לפי כמות ה-app model שהיא נושאת.

5.3 WinForms / WPF קלים ל-migration, אבל נשארים Windows-only

WinForms ו-WPF יכולים לעבור ל-.NET. עם זאת, שניהם נשארים framework-ים Windows-only.

טעות בציפייה כאן מסוכנת.

  • מה שמשתפר
    • עולים על runtime, שפה ו-SDK-style של modern .NET
    • קל יותר להתאים CI/CD וניהול חבילות לימינו
    • זוכים לחלק משיפורי הביצועים והתחזוקה
  • מה שלא משתנה
    • היות Windows-only
    • נשארות בעיות תאימות של בקרות UI ורכיבים ל-design-time
    • בעיות ActiveX / COM / native DLL לא נעלמות

בנוסף, יש מקרים שבהם WinForms / WPF דורשים בדיקת השפעת BinaryFormatter. בפרט, כשקשור ל-clipboard, drag & drop, ResX, וסריאליזציה ב-design-time עם custom type, זה נוטה לצוף כשמעלים את ה-target ל-.NET 9 ומעלה.

הציפייה ל-migration של WinForms / WPFWinForms ו-WPF יכולים לעבור ל-.NET ולעלות על הזרימה של ה-runtime, השפה וה-SDK-style המודרני, אבל נשארים Windows-only, וגם נדרשת לפעמים בדיקת BinaryFormatter.migration של WinForms / WPFעולים על היתרונות של modern .NETנשארים Windows-onlyנדרשת לפעמים בדיקת BinaryFormatter

איור 15: ה-UI השולחני יכול לעבור, אבל התכונה של להיות Windows-only ממשיכה איתו.

5.4 ASP.NET Framework זה לא “migration של runtime” אלא “migration של app model”

המעבר מ-ASP.NET Framework ל-ASP.NET Core מוגדר גם במדריך של Microsoft כ-non-trivial. זה לא רק כי שמות ה-API משתנים, אלא כי הארכיטקטורה שמונחת ביסוד שונה.

המקומות שבהם ההבדל בולט הם בערך אלה:

  • Hosting model
  • Middleware pipeline
  • Request processing model
  • Session / Cache
  • Authentication / Authorization
  • Configuration
  • Dependency Injection
  • Logging / Monitoring

מה שכדאי לבדוק קודם באפליקציית ASP.NET Framework הוא בערך אלה:

  • מאיזה route / endpoint אפשר להעביר קודם
  • האם אפשר להסיר תלות ב-System.Web מ-shared library
  • איך מתאימים authentication / session / טיפול ב-exceptions / logs
  • האם עוברים incremental בלי לעצור את ה-production

בפרט, באפליקציה גדולה, מעשי יותר לתכנן מראש בהנחת incremental migration.

migration של ASP.NET הוא migration של app modelהמעבר מ-ASP.NET Framework ל-Core הוא לא החלפת שמות API אלא migration של app model עם שינוי בארכיטקטורה שביסוד: hosting, middleware, authentication, configuration, DI. באפליקציה גדולה מעשי יותר להניח incremental migration.באפליקציה גדולהASP.NET Framework → Coreהארכיטקטורה שביסוד משתנהhosting, middleware, authentication, configuration, DIתכנון בהנחת incremental migration

איור 16: ה-migration ב-ASP.NET הוא לא migration של runtime אלא של app model, וככל שההיקף גדול, ההנחה ההדרגתית טבעית יותר.

5.5 Web Forms נכנסים דרך פירוק אחריות, לא דרך “העברת נכסים”

Web Forms לא באותו app model כמו ASP.NET Core. לכן, באומדן, בטוח יותר לא להניח שאפשר להעביר את מסכי ה-UI כמו שהם.

בשטח, לרוב מתחילים מהפירוק הבא:

  • הפרדה בין לוגיקת מסך ל-business logic
  • פירוק האחריות שקבורה ב-Page / UserControl / ViewState
  • הוצאת business logic וגישה לנתונים ל-shared library
  • הרכבה מחדש של ה-UI במודל אחר כמו Razor Pages / MVC / Blazor

כלומר, בפרויקט Web Forms, מה שחשוב הוא האם יש תכנית פירוק אחריות לפני migration של ה-runtime.

Web Forms נכנסים דרך פירוק אחריותWeb Forms אינם באותו app model כמו ASP.NET Core, ולכן מפרידים בין לוגיקת מסך ל-business logic, מוציאים לוגיקה ל-shared library, ומרכיבים מחדש את ה-UI במודל אחר.הנחה של העברה כמו שזהמסכי Web Formsהפרדה בין לוגיקת מסך ל-business logicהוצאת הלוגיקה ל-shared libraryהרכבה מחדש של ה-UI במודל אחרהאומדן קורס

איור 17: מסתכלים על Web Forms לא כהעברת נכסים אלא כפירוק אחריות ואז הרכבה מחדש במודל אחר.

5.6 מפרידים בין חשיבה על WCF client ל-WCF server

כאן בטוח יותר לא לכרוך יחד.

WCF client

ל-WCF Client יש חבילת NuGet נתמכת ל-modern .NET. לכן, יש מקרים שבהם אם רק קוראים ל-WCF, זה לא כבד כמו שנראה.

WCF server

מצד שני, צד ה-host של שירות WCF שונה. במדריך של Microsoft מנחים בעיקר בשני מסלולים לצורך modernization:

  • כיוון של שימוש ב-CoreWCF לשמירת תאימות ללקוחות קיימים
  • כיוון של מעבר ל-RPC / HTTP מודרני כמו gRPC

עם זאת, CoreWCF לא מביא את כל WCF כמו שהוא — זו תת-קבוצה. מתאים לשמירת תאימות ללקוחות קיימים, אבל שינוי קוד ובדיקה הם הנחת יסוד.

WCF מוערך בנפרד ללקוח ולשרתל-WCF client יש חבילה נתמכת ל-modern .NET ולעיתים זה לא כבד כמו שנראה, ואילו בצד השרת צריך לבחור מסלול: שמירת תאימות עם CoreWCF, שהוא תת-קבוצה, או תכנון מחדש עם gRPC.clientserverשמירת תאימותתכנון מחדשבאיזה צד משתמשים ב-WCFmigration עם חבילה נתמכתבוחרים מסלולCoreWCF (תת-קבוצה)gRPC / HTTP API

איור 18: לצד הקורא ולצד ה-host יש קושי ואפשרויות שונים, ולכן לא אומדים אותם יחד.

6. סורקים טכנולוגיות שאי אפשר להשתמש בהן ב-.NET, או שקל להיתקע בהן כמו שהן

זו נקודה שחייבים לבצע לפני שמתחילים. ל-Microsoft יש רשימה של טכנולוגיות שהיו זמינות ב-.NET Framework אבל לא זמינות ב-.NET 6 ומעלה.

6.1 טכנולוגיות שנוטות להיות red flag

טכנולוגיה המצב ב-.NET איך לחשוב על זה
AppDomain.CreateDomain וכדומה — יצירת AppDomain לא נתמך חושבים על isolation דרך process נפרד / container / AssemblyLoadContext
.NET Remoting לא נתמך תכנון מחדש ל-IPC, HTTP, gRPC, Socket, Pipe וכדומה
CAS / Security Transparency לא נתמך כגבול אבטחה חושבים על OS / container / הפרדת הרשאות
System.EnterpriseServices (COM+) לא נתמך מפרידים או מחליפים את התכנון שמניח COM+
Workflow Foundation לא נתמך חושבים באומדן נפרד, כולל חלופות כמו CoreWF
WCF server לא built-in כמו שהוא בוחרים בין CoreWCF ל-gRPC
BinaryFormatter מ-.NET 9 ואילך, המימוש תמיד זורק exception מעבר ל-serializer אחר, audit של ResX / clipboard / drag & drop

6.2 AppDomain הוא “גם אם חלק מה-API נשאר, היצירה עניין נפרד”

סביבת AppDomain קצת מסובכת. גם ב-.NET, חלק ממשטח ה-API נשאר, אבל השימוש של יצירת AppDomain חדש ו-isolation בו לא נתמך.

לכן, אם השתמשו ב-AppDomain לצרכים הבאים, נדרש תכנון מחדש:

  • isolation של plugin
  • ביטול טעינה דינמית
  • isolation של קוד באמון חלקי
  • הפרדת סביבת הרצה זמנית

מה שכדאי לבדוק לפני ה-migration הוא לא רק האם המילה AppDomain מופיעה, אלא לשם מה השתמשו ב-AppDomain.

השימוש ב-AppDomain קובע את ההחלטהלמרות שחלק מה-API נשאר, השימוש ביצירת AppDomain חדש ו-isolation בו לא נתמך, ולכן מבחינים בין שימוש בטיפוס בלבד לבין isolation בפועל. ל-isolation נדרש תכנון מחדש ב-process נפרד או AssemblyLoadContext.רק שימוש בטיפוס או במידעיצירה ו-isolationAppDomain מופיעברוב המקרים אפשר להמשיך כמו שזהנדרש תכנון מחדשprocess נפרד / container / AssemblyLoadContext

איור 19: לא לפי הימצאות המילה אלא לפי “לשם מה השתמשו בזה” נקבע אם נדרש תכנון מחדש.

6.3 Remoting עמוק ממה שנראה

מלבד Remoting עצמו, גם delegate אסינכרוני כמו קריאה ל-BeginInvoke() / EndInvoke() עלול להיכנס להיקף ההשפעה. זה לא Remoting עצמו, אבל הוא לא נתמך ב-modern .NET, ולכן צריך לעשות לו inventory לפני ה-migration.

לכן, בעת החיפוש, בטוח יותר לבדוק גם אלה יחד:

  • System.Runtime.Remoting
  • MarshalByRefObject
  • RealProxy
  • BeginInvoke( / EndInvoke(

6.4 BinaryFormatter צף לפתע לפי target version

BinaryFormatter, ככל שבסיס הקוד ישן יותר, נוטה להשתמש בו בלי מודעות.

  • נתונים שנשמרים
  • cache
  • שמירת session
  • מצב plugin
  • clipboard / drag & drop
  • ResX
  • סביבת ה-designer של WinForms / WPF

מ-.NET 9 ואילך, BinaryFormatter לא כולל מימוש ב-runtime, וה-API תמיד זורק PlatformNotSupportedException. כלומר, זה לא נושא ל”נחשוב על זה אחר כך”, אלא נקודה שדורשת audit מוקדם ברגע שקובעים את ה-target version.

המסלול שבו BinaryFormatter צףBinaryFormatter נוטה להיות בשימוש בלי מודעות דרך נתונים שנשמרים, ResX וכדומה, ומ-.NET 9 ואילך ה-API זורק תמיד exception, ולכן זו נקודה שדורשת audit מוקדם ברגע שקובעים את ה-target version.שימוש בלי מודעות (ResX, clipboard וכדומה)קביעת target ל-.NET 9 ואילךה-API תמיד זורק exceptionדורש audit מוקדם ברגע ההחלטה

איור 20: BinaryFormatter משפיע ברגע שקובעים את ה-target, ולכן לא דוחים אותו — מבצעים audit מוקדם.

6.5 מונחי חיפוש שכדאי לעשות עליהם grep קודם

עוד לפני שמתחילים, חיפוש ה-solution כולו לפי המונחים הבאים כבר משנה משמעותית את התמונה.

System.Web
HttpContext.Current
System.Runtime.Remoting
MarshalByRefObject
AppDomain
BinaryFormatter
ServiceHost
ChannelFactory
System.EnterpriseServices
Workflow
packages.config
web.config.install.xdt
install.ps1
DllImport
AxInterop
Microsoft.Office.Interop

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

פקודת החיפוש בפועל

הכלי יכול להיות rg (ripgrep) או PowerShell.

# PowerShell. חיפוש מרוכז בכל ה-solution
Get-ChildItem -Recurse -Include *.cs,*.vb,*.config,*.csproj,*.vbproj |
    Select-String -Pattern 'BinaryFormatter|System\.Runtime\.Remoting|MarshalByRefObject|AppDomain\.CreateDomain' |
    Select-Object Path, LineNumber, Line
# ripgrep. כשרוצים קודם לקבל תחושה לפי מספר התוצאות
rg -n --stats "BinaryFormatter|System\.Runtime\.Remoting|AppDomain\.CreateDomain" --glob "*.cs" --glob "*.vb"

מה עושים אחרי שנמצא

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

מונח שנמצא מה בודקים אחר כך הפתרון
System.Web / HttpContext.Current האם אפשר להוציא את זה מחוץ ל-shared library. האם צד הקריאה יכול לארוז ל-DTO הסרה עם האסטרטגיה בפרק 8.5
System.Runtime.Remoting / MarshalByRefObject / BeginInvoke לשם מה נועדה קריאת ה-remote. בין processes, בין מכונות, או רק קריאה אסינכרונית פשוטה תכנון מחדש עם IPC, HTTP, gRPC, מבוסס Task
AppDomain האם משתמשים רק בשם הטיפוס, או מבודדים עם CreateDomain אם המטרה isolation, process נפרד או AssemblyLoadContext (6.2)
BinaryFormatter האם צריך לקרוא אחר כך את הנתונים שנכתבו. האם משתמשים בזה בעקיפין דרך ResX או clipboard מעבר ל-serializer אחר, ותכנון לקריאה מחדש של הנתונים הקיימים (6.4)
ServiceHost / ChannelFactory צד ה-host או צד ה-client הערכה נפרדת לפי 5.6
packages.config / install.ps1 / web.config.install.xdt מה נכתב מחדש בזמן ההתקנה ה-gotcha מ-4.2. מחזיקים את ההגדרה במפורש
DllImport / AxInterop / Microsoft.Office.Interop הנחת מספר הביטים וכל קובצי ה-runtime הנדרשים בדיקת bitness בפרק 9.4

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

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

איור 21: החיפוש עצמו הוא הכניסה, וכשמקדמים אותו עד ההחלטה, מתקבלת בדיוק הרשימה הרצויה לפני שמתחילים.

7. קובעים עד כמה מקבלים הנחת Windows-only

טעות נפוצה ב-migration היא “אם עברנו ל-.NET, זה נהיה cross-platform”. אין קסם כזה. אם האפליקציה קשורה עמוק ל-Windows, גם אחרי ה-migration היא נשארת Windows-only כרגיל.

7.1 להישאר Windows-only ב-migration הוא ריאלי לגמרי

ל-Microsoft יש Windows Compatibility Pack, שמאפשר לגשת מ-modern .NET להרבה Windows API כמו Registry, WMI, EventLog, Windows Service ו-Directory Services.

הקיום שלו משמעותי בשטח.

  • רוצים קודם לעבור ל-modern .NET
  • אבל בינתיים לא יוצאים מ-Windows
  • אז רוצים לקבל בינתיים את תלות ה-Windows API

בסביבה כזו, זו אפשרות חזקה.

המטרה הראשונה של ה-migration לא חייבת להיות הפיכה ל-cross-platform.

7.2 עם זאת, גם Windows-only API הוא חוב שישפיע בהמשך

עצם קיומו של Windows Compatibility Pack לא אומר שהכול בטוח.

  • רוצים לשים על Linux container
  • רוצים להריץ בהנחת Kubernetes
  • גם מפתחי macOS / Linux רוצים להריץ את אותו build
  • בעתיד, רוצים להפחית Windows VM בענן

אם יש מטרות כאלה, בטוח יותר לחשוף כבר עכשיו את תלות ה-Windows API.

מקום השימוש ב-Windows Compatibility Pack והחוב שמאחוריואם בינתיים נשארים על Windows, Windows Compatibility Pack מאפשר לקבל בינתיים את תלות ה-Windows API ולעבור ל-modern .NET. אם שואפים בעתיד ל-container או cloud, התלות היא חוב שישפיע בהמשך ולכן חושפים אותו כבר עכשיו.בינתיים נשארים על Windowsאם שואפים בעתיד ל-container / cloudרוצים קודם לעבור ל-modern .NETWindows Compatibility Pack מקבל בינתיים את התלותהתלות היא חוב שישפיע בהמשךחושפים אותו כבר עכשיו

איור 22: Windows Compatibility Pack הוא גשר ריאלי, אבל התלות שלו עלולה להיות חוב לפי המטרה, ולכן חושפים אותה מראש.

7.3 System.Drawing.Common קל במיוחד לטעות בהבנתו

System.Drawing.Common הוא, מ-.NET 6 ואילך, ספרייה Windows-only. אם יש קוד שמשתמש בעיבוד תמונות או ציור טקסט, צריך לקבוע קודם באיזה כיוון הולכים.

  • ממשיכים לתפעל על Windows
  • בעתיד רוצים להריץ גם על Linux / macOS

באפשרות הראשונה יש מקרים שאפשר להישאר כמו שזה בינתיים. באפשרות השנייה, צריך לכלול מראש בתכנון ה-migration החלפה כמו SkiaSharp או ImageSharp.

ההסתעפות של System.Drawing.CommonSystem.Drawing.Common הוא Windows-only מ-.NET 6 ואילך. אם ממשיכים על Windows אפשר להישאר כמו שזה בינתיים, ואם רוצים להריץ גם על Linux או macOS צריך לכלול מראש החלפה כמו SkiaSharp או ImageSharp.ממשיכים על Windowsרוצים גם Linux / macOSמשתמשים ב-System.Drawing.Commonאפשר להישאר כמו שזה בינתייםהחלפה ל-SkiaSharp / ImageSharpכוללים זאת מראש בתכנון ה-migration

איור 23: מכיוון ש-System.Drawing.Common הוא Windows-only, אופן הטיפול בו נחלק כבר בהתחלה לפי נקודת היעד.

7.4 סימנים ייצוגיים לקיבוע ל-Windows

כשיש הפניות או API-ים מהסוג הבא, בטוח יותר לאמוד “לפחות בהתחלה נשארים Windows-only”.

  • Microsoft.Win32.Registry
  • System.Management
  • System.Diagnostics.EventLog
  • System.ServiceProcess
  • System.DirectoryServices
  • System.Drawing
  • DllImport / P/Invoke
  • הפניית COM
  • AxInterop.*
  • Microsoft.Office.Interop.*

8. אופן הוצאת ה-shared library קובע את הקושי

ב-solution גדול, אין הגזמה לומר שהצלחת ה-migration נקבעת לפי איך חותכים את ה-shared library.

8.1 קודם מסווגים

נוח יותר לסווג ספריות לשלושה סוגים עיקריים:

  1. business logic / domain logic טהורה
  2. שכבת ביניים שתלויה מעט ב-app model
  3. שכבה שצמודה ל-UI / Web / Windows API

מבין אלה, מה שכדאי להעביר קודם הוא 1.

  • חישוב
  • הכרעת חוקים
  • DTO / חוזה
  • domain service
  • המרת נתונים פשוטה

אם מוציאים את זה נקי, הקושי הכולל יורד בבת אחת.

שלוש הקטגוריות של הספריות וסדר ההעברהמחלקים ספריות ל-business logic טהורה, שכבת ביניים תלויית app model, ושכבה צמודה ל-UI ול-Windows API. מה שכדאי להעביר קודם הוא ה-business logic הטהורה.מעבירים ראשונהאחריהאחרונהbusiness logic טהורהאם מוציאים נקי, הקושי יורדשכבת ביניים תלויית app modelשכבה צמודה ל-UI / Windows API

איור 24: מחלקים את הספריות לשלוש שכבות, ומצילים בהדרגה מהלוגיקה הטהורה.

8.2 netstandard2.0 הוא עדיין גשר תקף

לפי ההנחיה של Microsoft, אם יש shared library שצריכה להתקיים גם בצד .NET Framework, הבסיס הוא לחשוב קודם על .NET Standard 2.0.

חשוב כאן שתי נקודות:

  • .NET Framework לא תומך ב-.NET Standard 2.1
  • אם רוצים להפנות ל-shared library גם מהישן וגם מהחדש, 2.0 הוא הפתרון המעשי ברוב המקרים
הגשר בשם netstandard2.0.NET Framework לא תומך ב-.NET Standard 2.1, ולכן אם רוצים להפנות ל-shared library גם מהישן וגם מהחדש, .NET Standard 2.0 הוא הפתרון המעשי.יכול להפנותיכול להפנותFramework לא תומךצד .NET Frameworkshared library ב-netstandard2.0צד modern .NETnetstandard2.1

איור 25: כגשר שנגיש גם מהישן וגם מהחדש, הפתרון המעשי הוא 2.0 ולא 2.1.

8.3 מה משתנה כשעוברים ל-netstandard2.0

מדיניות מה משתנה מתי מתאים הערה
המרה ל-netstandard2.0 קל להפנות גם מהישן וגם מהחדש business logic טהורה, חוזה משותף, utilities לא ניתן לטעון API ייחודי ל-app model
multi-target (למשל: net48;net10.0) שומרים על קוד משותף ובכל זאת מחזיקים הפרש לפי סביבה ספרייה עם הפרש קטן בין סביבות מוסיף התניות וניהול build
המרה ישירה ל-net10.0 בלבד הכי נקי בעתיד שכבה חדשה שלא צריכה תלות בין ישן לחדש לא ניתן להפניה מ-.NET Framework

8.4 מצב תאימות אינו כל-יכול

ל-.NET Standard 2.0 יש מצב תאימות שמאפשר להפנות לספריות .NET Framework. עם זאת, זה לא קסם שגורם לכול לפעול באופן שקוף.

לדוגמה, ספרייה שמניחה API ייחודי ל-app model כמו WPF קשה כרגיל. כלומר, גם אם אומרים shared library, חשוב להצר רק לאחריות שבאמת ניתנת לשיתוף.

8.5 בספריות מסוג ASP.NET, המפתח הוא האם אפשר להסיר את System.Web

כשמבצעים incremental migration ל-ASP.NET Framework, אם ל-shared library יש תלות ישירה ב-HttpContext.Current או ב-System.Web, זה די קשה.

האסטרטגיה הבסיסית כאן היא אחת מאלה:

  • דחיפת התלות ב-System.Web אל מחוץ לממשק
  • שינוי לקבלת מידע שמקורו ב-HttpContext כ-DTO
  • שימוש ב-adapter בתקופת המעבר
  • אם עדיין קשה, הסרה הדרגתית עם multi-target

8.6 מעלים ספריות בשיטת leaf-first

במדריך ה-incremental migration של ASP.NET כתוב במפורש שמעלים supporting library ב-postorder depth-first, כלומר מהעלים ראשון.

זה לא מוגבל ל-Web, אלא יעיל מאוד גם ב-solution-ים רגילים.

  • מכיוון שהיעדים שהם תלות עלו קודם, קל יותר לראות את השכבה העליונה
  • קל יותר לבודד בעיות תאימות
  • קל יותר לבדוק ברמת ספרייה
מעלים בשיטת leaf-firstאם מעלים את ספריות התמיכה מהעלים של התלות ראשון, שכבת הביניים אחריהן, ולבסוף שכבת האפליקציה העליונה, קל יותר לבודד בעיות ולבדוק ברמת ספרייה.מעלים ראשית את ספריות העליםמעלים את שכבת הביניים שסיימהלבסוף שכבת האפליקציה העליונהאפשר לבודד ולבדוק בעיות

איור 26: כשמעלים מהעלים ראשון, עד שמגיעים לשכבה העליונה, הבסיס כבר מוכן.

9. סורקים NuGet / תלויות חיצוניות / רכיבי צד שלישי

אם עושים את זה ברשלנות, זה יכאב הכי הרבה בשלב השני של ה-migration.

9.1 נוח יותר לחלק את התלויות לארבעה סוגים

  1. חבילת NuGet ציבורית
  2. חבילה פרטית פנימית / internal library
  3. הפניית DLL מקומית
  4. COM / ActiveX / native DLL / SDK

מתוכם, לא מספיק להסתכל רק על 1. מה שבאמת מסוכן הם 3 ו-4.

ארבע קטגוריות התלות ורמת הסיכוןהתלויות מחולקות לחבילת NuGet ציבורית, חבילה פנימית, הפניית DLL מקומית, ו-COM/ActiveX/native DLL. המסוכנים באמת הם ההפניה המקומית וה-COM/native.inventory של תלויותNuGet ציבורית / חבילה פנימיתהפניית DLL מקומיתCOM / ActiveX / native DLLהמסוכן באמת הוא הצד הזה

איור 27: לא מספיק לספור NuGet ציבורי — קודם סורקים DLL מקומי ו-COM / native.

9.2 מה בודקים בכל תלות

לגבי כל תלות, לפחות בודקים עד כאן:

  • האם היא ממוקדת ל-modern .NET
  • האם היא תומכת ב-PackageReference
  • האם אין בעיה עם SDK-style
  • האם יש מגבלה ל-x86 / x64 / ARM64
  • האם היא תלויה בכלי design-time או בתוסף Visual Studio
  • האם היא מניחה install script / config transform
  • האם התמיכה עדיין נמשכת

9.3 UI / דוחות / רכיבי design-time של צד שלישי — מאמדים בנפרד

ב-migration של WinForms / WPF / ASP.NET, זה משפיע משמעותית.

  • Grid
  • מנוע דוחות
  • רכיב פלט PDF
  • רכיב גרפים
  • ספריית UI משולבת עם designer
  • עטיפת ActiveX

אלה קשורים לא רק ב-runtime, אלא גם בתמיכה ב-design-time. אם באומדן ה-migration בודקים רק “האם זה מתקמפל”, בדרך כלל מפספסים אותם.

9.4 בודקים תמיד native DLL ו-bitness

גם אם נראה שרץ ב-AnyCPU בתקופת .NET Framework, ייתכן שבפועל יש תלות בדברים מהסוג הבא:

  • COM שקבוע ל-x86
  • ActiveX ייעודי ל-32bit
  • גרסה מסוימת של VC++ Runtime
  • native DLL חתום

זו לא בעיה חדשה שצמחה עם המעבר ל-modern .NET, אלא מגבלה שהייתה קיימת מהתחלה, וצפה עכשיו. בדיוק בגלל זה שווה לחשוף אותה לפני ה-migration.

הצפת מגבלת ה-bitnessגם אם נראה שרץ ב-AnyCPU, ייתכן תלות ב-COM קבוע ל-x86, ActiveX ל-32bit או גרסה מסוימת של VC++ Runtime. אלה מגבלות שהיו קיימות מהתחלה שצפות בגלל ה-migration.נראה שרץ ב-AnyCPUתלות ב-COM x86, ActiveX 32bit וכדומהה-migration גורם למגבלה הקיימת לצוףחושפים אותה לפני ה-migration

איור 28: בעיית ה-bitness לא נוצרת על ידי ה-migration, אלא מגבלה קיימת שנעשית גלויה.

10. מטפלים ב-EF6, ב-serializer-ים ובנתונים כבעיה נפרדת

עדיף ככל האפשר להתייחס בנפרד ל-migration של ה-runtime ולתכנון מחדש של גישת הנתונים והסריאליזציה.

10.1 המעבר מ-EF6 ל-EF Core הוא לא שדרוג ישיר

גם במדריך ה-EF של Microsoft כתוב ש-EF Core הוא כתיבה מחדש מלאה של EF6, ואין נתיב שדרוג ישיר.

לכן, באפליקציה שמשתמשת ב-EF6, הסדר הבא ריאלי:

  1. קודם עוברים ל-modern .NET
  2. אם צריך, ממשיכים להריץ עם EF6 כמו שהוא
  3. אחר כך מעבירים ל-EF Core כפרויקט נפרד

לא לערבב בין runtime migration ל-ORM migration. רק זה כבר מוריד משמעותית את הקושי.

הפרדת ה-migration של EF6 מזה של runtimeEF Core הוא כתיבה מחדש מלאה של EF6 בלי נתיב שדרוג ישיר, ולכן ריאלי לעבור קודם ל-modern .NET, להמשיך עם EF6 אם צריך, ורק אחר כך להעביר ל-EF Core כפרויקט נפרד.אם עושים בו-זמניתקודם עוברים ל-modern .NETממשיכים עם EF6 אם צריךאחר כך מעבירים ל-EF Core כפרויקט נפרדהבדלי התנהגות ה-ORM מתערבבים ומכבידים

איור 29: לא מריצים בו-זמנית runtime ו-ORM — מעשי יותר להשאיר את EF6 קודם ולהעביר את ה-runtime.

10.2 מה משתנה כשמשאירים EF6

  • יתרון
    • אפשר לדחות את ההפרש בשכבת גישת הנתונים
    • אפשר להתמקד בהעברת business logic ו-app model
    • “הבדל התנהגות של EF Core” לא מתערבב
  • הערה
    • מנקודת מבט של פיתוח חדש, EF Core הוא הבחירה העיקרית
    • יש מגבלות נפרדות לצורת שימוש עם EF6 Designer / EDMX

10.3 EF6 מבוסס EDMX דורש התייחסות גם ב-design-time

בתיעוד EF6 כתוב ש-EF Designer לא נתמך ישירות בפרויקטי .NET / .NET Standard, או בפרויקטי .NET Framework ב-SDK-style.

באפליקציה מבוססת EDMX, צריך להתייחס בנפרד לשלוש נקודות אלה:

  • האם זה פועל ב-runtime
  • האם ה-Designer שמיש
  • איך מטפלים בקוד שנוצר

אם יש שימוש נרחב ב-EDMX, בטוח יותר לכלול את זה באומדן כבר מההתחלה.

10.4 BinaryFormatter וסריאליזציה עצמית נוטים להיות תלות נסתרת

קל לפספס serializer-ים רק בעזרת חיפוש קוד.

  • פורמט נתונים לשמירה
  • מסרים
  • cache
  • חוזה WCF / SOAP ישן
  • ResX
  • clipboard / drag & drop

אלה קשורים גם לתאימות נתונים. כלומר, לא מספיק “האם ה-build עובר”, אלא נדרשת בדיקה עד להאם אפשר לקרוא נתונים ישנים.

11. כוללים גם תצורה, הפצה, תפעול ו-CI/CD ביעד ה-migration

יעד ה-migration הוא לא רק קוד המקור.

11.1 קובצי תצורה

בצד .NET Framework, לעיתים יש הרבה מוטמע ב-app.config / web.config.

  • connection string
  • custom config section
  • הגדרת endpoint של WCF
  • Binding Redirect
  • diagnostics
  • הגדרות שונות של ASP.NET
  • תוצאת ה-transform בזמן התקנת חבילה

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

מה שעושים ראשון הוא inventory של התצורה.

  • מה מוטמע בקובץ התצורה
  • מה חובה בזמן הפעלת האפליקציה
  • מה ההפרש בין סביבות
  • מה הוזרק אוטומטית על ידי NuGet או installer

11.2 שיטת ההפצה

גם צורת ההפצה נבדקת לפני שמתחילים.

  • תחת IIS
  • Windows Service
  • Scheduled Task
  • ClickOnce / MSI / installer עצמאי
  • הנחת שרת מקומי
  • מה מתאים יותר — self-contained או framework-dependent

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

11.3 לוגים, ניטור, נהלי תפעול

גם סביב התפעול קל לפספס.

  • האם מבוסס Windows Event Log
  • האם מסתכלים על Performance Counter
  • האם ניטור מבוסס WMI
  • האם חשבון השירות וההרשאות קבועים
  • האם יעד פלט הלוגים מניח קובץ מקומי

קורה בהחלט שהקוד רץ אחרי ה-migration, אבל התפעול לא מסתובב.

11.4 CI/CD ו-build agent

לפני ה-migration, בודקים גם את אלה:

  • האם ה-.NET SDK הנדרש נכנס ל-build agent
  • מה עושים עם pipeline שמניח nuget.exe / msbuild.exe
  • האם עוברים בסיס dotnet CLI
  • איך מעדכנים את עבודות הריצת הבדיקות, coverage ו-publish
  • האם תבנית פנים-ארגונית או reusable pipeline מניחים צורה ישנה

עובד בסביבה המקומית של האדם אבל ה-CI מת זו תופעה נפוצה ב-migration.

יעד ה-migration הוא לא רק הקודגם אם גוף ההרצה עובר, אם קובצי התצורה, שיטת ההפצה, הלוגים והניטור, וה-CI/CD ו-build agent נשארים בהנחה ישנה, זה נתקע בסוף. לכן כל אלה נכללים ביעד ה-migration.migration של קוד המקורזה לא מסתיים בזה בלבדקובצי תצורה ושיטת הפצהלוגים, ניטור, נהלי תפעולCI/CD ו-build agentעובד מקומית אבל ה-CI מת

איור 30: רק כשכוללים תצורה, הפצה, תפעול ו-CI/CD, זה נחשב שסופרו כל יעדי ה-migration.

12. אופן ההתקדמות המעשי של ה-migration

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

12.1 קודם מכינים את צד ה-Framework הנוכחי

  1. עלייה ל-.NET Framework 4.7.2 ומעלה, אם אפשר ל-4.8.1
  2. עדכון התלויות
  3. בדיקה מחדש של packages.config
  4. ככל האפשר, מעבר ל-PackageReference ול-SDK-style
  5. אימות שהאפליקציה הנוכחית רצה תקין במצב הזה

רק ביצוע השלב הזה מצמצם משמעותית את ה-gap בשלב הבא.

12.2 מצילים קודם shared library

בשלב הבא, מעבירים business logic וחוזים משותפים ל-netstandard2.0 או ל-multi-target. סדר ההעלאה הבסיסי הוא leaf-first.

12.3 מחליפים אסטרטגיה לגוף האפליקציה לפי app model

  • class library / console / חלק מהשירותים יחסית קל להתקדם ישירות
  • WinForms / WPF modernization תוך שמירה על Windows-only
  • ASP.NET MVC / Web API אם קטן — בבת אחת, אם כבד — incremental
  • Web Forms בהנחת החלפת מסכי ה-UI, מוציאים תחילה לוגיקה משותפת
  • WCF server קובעים קודם — שמירת CoreWCF, או תכנון מחדש עם gRPC

12.4 שומרים על “לא לעשות הכול בבת אחת”

בפרט, מה שכדאי להימנע ממנו הוא שילובים מהסוג הבא:

  • runtime migration + החלפה כוללת ל-ORM
  • runtime migration + שינוי תשתית authentication
  • runtime migration + מעבר מלא ל-cloud
  • runtime migration + שינוי תשתית monitoring
  • runtime migration + חידוש תשתית UI

גם אם כולם נדרשים בסופו של דבר, לא לצבור אותם באותו sprint לרוב מוביל להצלחה.

12.5 פועלים רק אחרי שיש בדיקות ו-baseline

לפחות, כדאי להכין את זה לפני שמתחילים לפעול:

  • unit tests
  • integration tests לזרימות עסק מרכזיות
  • אימות “תמונת מצב” למסכים / API-ים ייצוגיים
  • baseline ביצועים
  • שיטת אימות לוגים מרכזיים
  • נוהל rollback

להתקדם במצב שבו אי אפשר לזהות “מה נשבר” אחרי ה-migration, מסוכן למדי.

מה מכינים לפני שמתחילים לפעולאם מכינים בדיקות ו-baseline, לוגים ונהלי rollback לפני שמתחילים לפעול ב-migration, אפשר לזהות מה נשבר אחריו. התקדמות בלי הכנה מסוכנת.הכנת בדיקות ו-baselineרק אז מתחילים לפעול ב-migrationאפשר לזהות מה נשברהתקדמות בלי הכנהאי-זיהוי במקרה תקלה — מסוכן

איור 31: ה-migration נקבע לפי ההכנה שלפני הפעולה, ורק עם baseline אפשר לזהות מה נשבר.

13. צ’קליסט לפני שמתחילים

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

13.1 מדיניות

  • אפשר להסביר במשפט אחד למה עושים את ה-migration
  • נקבע האם נקודת היעד הפעם היא modern .NET Windows-only, או cross-platform בעתיד
  • נקבעה גרסת .NET היעד
  • נקבע מה לא נכלל בהיקף הזה (הפיכה ל-EF Core, חידוש authentication, מעבר מלא ל-cloud וכדומה)

13.2 הכנת צד .NET Framework הנוכחי

  • הועלה ל-.NET Framework 4.7.2 ומעלה, אם אפשר ל-4.8.1
  • התלויות עלו לגרסה עדכנית
  • נסרק קיום packages.config
  • נבדקה היתכנות המרה ל-PackageReference
  • נבדקה היתכנות מעבר ל-SDK-style
  • האפליקציה הנוכחית מסוגלת ל-build, הפעלה ובדיקה במצב הזה

13.3 סוג האפליקציה ובחירת טכנולוגיה

  • הקושי חולק לפי סוג — class library / desktop / Web / WCF וכדומה
  • מובן ש-WinForms / WPF נשארים Windows-only
  • מובן ש-ASP.NET Framework הוא migration של app model ל-ASP.NET Core
  • הוכללה באומדן החלפת שכבת UI ל-Web Forms
  • WCF הוערך בנפרד ל-client ול-server

13.4 טכנולוגיות לא נתמכות / API-ים שדורשים תשומת לב

  • נסרקה תלות ב-AppDomain
  • נסרקו Remoting / MarshalByRefObject / BeginInvoke / EndInvoke
  • נסרקו CAS / Security Transparency / COM+ / WF
  • נסרקה תלות ב-BinaryFormatter
  • נסרקה תלות ב-System.Web

13.5 תלות Windows-only

  • נסרק שימוש ב-Registry, WMI, EventLog, Windows Service, Directory Services
  • נסרק שימוש ב-System.Drawing.Common
  • נסרקו COM / ActiveX / Office Interop / P/Invoke / native DLL
  • נבדקה מגבלת x86 / x64 / ARM64

13.6 shared library וגישה לנתונים

  • shared library סווגו לbusiness logic / שכבה צמודה ל-app model
  • נסרק מה ניתן להמיר ל-netstandard2.0
  • נסרקו ספריות שדורשות multi-target
  • נקבע האם אפשר להשאיר EF6 ולהעביר קודם רק את ה-runtime
  • נבדקה תלות EDMX / Designer

13.7 תפעול ו-build

  • בוצע inventory של קובצי תצורה
  • נבדקה שיטת ההפצה (IIS / Service / MSI / ClickOnce וכדומה)
  • נבדקו הנחות logs / monitoring / הרשאות / חשבון הרצה
  • נבדק האם נדרש עדכון ל-CI/CD ול-build agent
  • הוכן נוהל rollback

14. סיכום

ב-migration מ-.NET Framework ל-.NET, מה שחשוב הוא לא “באיזו פקודה מעבירים”, אלא לזהות לפני שמתחילים מה עובר כמו שהוא ומה בעיה נפרדת.

אם מרכזים לנקודות, הנה שש אלה:

  • מכינים את צד .NET Framework לפני ה-migration
  • מחלקים את הקושי לפי app model
  • סורקים קודם טכנולוגיות שאי אפשר להשתמש בהן
  • קובעים עד כמה מקבלים הנחת Windows-only
  • קובעים איך חותכים את ה-shared library
  • לא לוקחים יותר מדי בבת אחת מ-ORM, authentication ו-migration ל-cloud

השבוע הראשון של ה-migration משנה משמעותית את דיוק האומדן. במילים אחרות, אם מפרקים את הסוגיות באותו שבוע, המחצית השנייה מתקרבת הרבה יותר לפיתוח רגיל.

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

איור 32: האם השבוע הראשון מנוצל ל-inventory, קובע את דיוק ה-migration כולו.

“בואו פשוט ננסה לשנות ל-net10.0” הוא לא רעיון רע לצורך חקירה. עם זאת, כ-migration בפועל ל-production, יש מה לבדוק לפני זה. זה בדיוק מה שסידרנו במאמר הזה.

15. מקורות

מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מה כדאי לעשות קודם לפני migration מ-.NET Framework ל-.NET?
לפני שנכנסים למימוש, קודם מסיימים את העבודה בצד .NET Framework. גם המדריך הרשמי של Microsoft ממליץ, לפני ה-port, לעלות ל-.NET Framework 4.7.2 ומעלה (בשטח, אם אפשר, 4.8.1), להמיר packages.config ל-PackageReference, לעבור ל-SDK-style project, ולעדכן תלויות לגרסה עדכנית יותר. אם עושים את זה קודם, ה-gap בשלב הבא של המעבר ל-modern .NET מצטמצם משמעותית, וקל יותר להפריד אם בעיית תאימות מגיעה מ-Framework ישן או מהמעבר ל-.NET. במקביל, גם עושים inventory של טכנולוגיות לא נתמכות כמו AppDomain, Remoting ו-BinaryFormatter לפני שמתחילים.
האם אפשר להחליט להישאר על .NET Framework?
כן, זו החלטה סבירה לגמרי. .NET Framework 4.8.1 ממשיך לקבל תמיכה כל עוד הוא רץ על Windows נתמך, ולכן זה לא מצב שבו חייבים מיד להעביר הכול ל-modern .NET. אם יש הרבה מסכי Web Forms, צריך לשמור בקפדנות על תאימות WCF server, יש תלות עמוקה ב-Workflow Foundation או ב-COM+, או שרכיבי design-time של צד שלישי לא נתמכים — הגיוני להישאר בינתיים על 4.8.1 עם תפעול יציב, ולתכנן החלפה בקו נפרד. עם זאת, נשארות מגבלות: אי אפשר לצאת מ-Windows-only, וקשה ליהנות מביצועים ותכונות שפה חדשות של .NET.
אילו טכנולוגיות אי אפשר להעביר ל-.NET, או שקל להיתקע בהן?
יצירת AppDomain, .NET Remoting, CAS (Code Access Security), COM+ (System.EnterpriseServices) ו-Workflow Foundation לא נתמכים ב-modern .NET, ואלה red flags שדורשים תכנון מחדש. WCF server לא רץ כמו שהוא built-in, ויש לבחור בין תכנון מחדש עם CoreWCF לבין gRPC / HTTP API. BinaryFormatter, מ-.NET 9 ואילך, לא כולל מימוש וזורק תמיד exception, ולכן נדרש audit שכולל נתונים שנשמרו, ResX וגם clipboard / drag & drop. בנוסף, install.ps1 / XDT של packages.config, native DLL, COM / ActiveX, והנחת x86 — כל אלה נקודות שדורשות תשומת לב, כי גם אם ה-build עובר, קל ליפול ב-runtime.
האם migration של WinForms או WPF ל-.NET הופך אותם ל-cross-platform?
לא. WinForms / WPF יכולים לעבור ל-.NET, אבל הם נשארים Windows-only. מה שמתקבל מה-migration הוא היתרונות של runtime, תכונות שפה, SDK-style ותאימות ל-CI/CD של modern .NET, אבל זה לא שם אותם על Linux container. אם בעתיד שואפים ל-Linux / containerization, צריך לעשות inventory מוקדם ל-API-ים שמניחים Windows כמו System.Drawing.Common, Registry, WMI, EventLog, Windows Service ו-Office Interop. לעומת זאת, אם ממשיכים Windows-only, אפשר לבחור במסלול מעשי שמודרניזציה קודם את ה-runtime בעזרת Windows Compatibility Pack.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג