יותר

CodeDom.Compiler נכשל בתוספת Arcmap, אך עובד מאפליקציית המסוף


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

לא ניתן היה לטעון את הקובץ או ההרכבה 'KompilerLib, גרסה = 1.0.0.0, תרבות = ניטראלית, PublicKeyToken = null' או אחת התלות שלו. המערכת לא יכולה למצוא את הקובץ שצוין.

KompilerLib הוא פרוייקט ספריית Windows class (3.5) וזה הקובץ היחיד בפרויקט (ממשק אחד ומחלקה אחת).

האם יש משהו מיוחד שעלי לעשות אם אני משתמש ב- CodeDom.Compiler בתוך תוסף?

באמצעות מערכת; באמצעות System.Collections.Generic; באמצעות System.Text; באמצעות System.CodeDom.Compiler; שימוש ב- System.Diagnostics; באמצעות System.IO; מרחב השמות KompilerLib {ממשק ציבורי IKalkulation {Test Test (); } מחלקה ציבורית Compiler {string const string TYPENAME = "Kalk.Kalkulation"; ציבורי IKalkulation Kompile (שפת מחרוזת, רשימה הפניות, מקור מחרוזת) {CodeDomProvider provider = CodeDomProvider.CreateProvider (שפה); פרמטרים של var = CompilerParameters חדשים (); parameters.GenerateInMemory = true; parameters.GenerateExecutable = false; foreach (הפניה למחרוזת בהפניות) {parameters.ReferencedAssemblies.Add (reference); } var results = provider.CompileAssemblyFromSource (פרמטרים, מקור); if (results.Errors == null || results.Errors.Count == 0) {Debug.Print (results.CompiledAssembly.ReflectionOnly.ToString ()); foreach (הקלד t בתוצאות. CompiledAssembly.GetTypes ()) Debug.Print (t.Name); var type = results.CompiledAssembly.GetType (TYPENAME); אם (type == null) זורק חריג חדש ("סוג לא נמצא:" + TYPENAME); אובייקט o = Activator.CreateInstance (סוג); אם (o == null) זורק Exception חדש ("לא מסוגל ליצור אינסטנס"); var kalkulation = o כמו IKalkulation; אם (kalkulation == null) זורק חריג חדש ("לא מסוגל ללהק ל- IKalkulation"); החזרת קלקולציה; } אחר {StringBuilder sb = StringBuilder חדש (); foreach (CompilerError err in results.Errors) sb.AppendLine (err.ErrorText); לזרוק חריג חדש (sb.ToString ()); }} בדיקת מחרוזת סטטית ציבורית () {var kompiler = Kompiler חדש (); var list = רשימה חדשה(); list.Add ("System.dll"); נתיב מחרוזת = kompiler.GetType (). Assembly.Location; אם (! File.Exists (path)) זורק חריג חדש ("קובץ לא נמצא" + נתיב); list.Add (נתיב); מקור מחרוזת = GetSource (); var kalk = kompiler.Kompile ("CSharp", רשימה, מקור); להחזיר את kalk.Test (); } מחרוזת סטטית פרטית GetSource () {StringBuilder sb = StringBuilder חדש (); sb.AppendLine ("באמצעות KompilerLib;"); sb.AppendLine ("מרחב השמות Kalk"); sb.AppendLine ("{"); sb.AppendLine ("Kalkulation בכיתה ציבורית: IKalkulation"); sb.AppendLine ("{"); sb.AppendLine ("מבחן מחרוזות ציבורי ()"); sb.AppendLine ("{"); sb.AppendLine ("להחזיר " שלום עולם  ";"); sb.AppendLine ("}"); sb.AppendLine ("}"); sb.AppendLine ("}"); החזר sb.ToString (); }}}

עדכון

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

ציבורי IKalkulation Kompile (שפת מחרוזת, רשימה הפניות, מקור מחרוזת) {CodeDomProvider provider = CodeDomProvider.CreateProvider (שפה); פרמטרים של var = CompilerParameters חדשים (); parameters.GenerateInMemory = true; parameters.GenerateExecutable = false; foreach (הפניה למחרוזת בהפניות) {parameters.ReferencedAssemblies.Add (reference); } // זה בטוח נראה כמו פריצה ... AppDomain.CurrentDomain.AssemblyResolve + = (s, args) => {if (args.Name == this.GetType (). Assembly.FullName) להחזיר this.GetType (). ; אחרת להחזיר אפס; }; var results = provider.CompileAssemblyFromSource (פרמטרים, מקור); אם (results.Errors == null || results.Errors.Count == 0) {var type = results.CompiledAssembly.GetType (TYPENAME); אם (type == null) זורק חריג חדש ("סוג לא נמצא:" + TYPENAME); אובייקט o = Activator.CreateInstance (סוג); אם (o == null) זורק Exception חדש ("לא מסוגל ליצור אינסטנס"); var kalkulation = o כמו IKalkulation; אם (kalkulation == null) זורק חריג חדש ("לא מסוגל ללהק ל- IKalkulation"); החזרת קלקולציה; } אחר {StringBuilder sb = StringBuilder חדש (); foreach (CompilerError err in results.Errors) sb.AppendLine (err.ErrorText); לזרוק חריג חדש (sb.ToString ()); }}

נתקלתי בבעיות דומות בעת שימוש ב- .NET מותאם אישיתסעיף תצורהוכאשר משתמשים בסידור בינארי (דה). בעיה זו נדונה בתגובות לשאלה זו: תוסף ArcMap עם app.settings שאינו מזהה שינויים ב- app.config?

נראה שהבעיה היא שחלק מההרכבות המוזכרות על ידי תוספות אינן ניתנות לפתרון כהלכה מכיוון שתחום יישום התוספת אינו נפרד מתחום היישום הראשי ולכן זמן הריצה של .NET נראה בנתיב הגששים של היישום הראשי לא מוצא אותם. התיקון הוא להשתמש Assembly.LoadFrom ולטפל ב AppDomain.AssemblyResolve מִקרֶה.

זה היה התיקון שעבד בשבילי עם המנהגסעיף תצורהנושא. אני מקווה שזה יעבוד גם במקרה שלך!


צפו בסרטון: How to Merge different Shapefiles in GIS Very Easy Method (אוֹקְטוֹבֶּר 2021).