Daugiau

„CodeDom.Compiler“ nepavyksta „Arcmap“ priede, tačiau veikia naudojant konsolės programą

„CodeDom.Compiler“ nepavyksta „Arcmap“ priede, tačiau veikia naudojant konsolės programą


Žemiau esančio kodo bandymo metodas sėkmingas konsolės bandymo programoje, bet nepavyksta, kai jį iškviečiu iš „Arcmap“ priedo, įmesdamas „ReflectionTypeLoadException“ su krautuvo išimtimi, sakydamas:

Nepavyko įkelti failo ar rinkinio „KompilerLib, versija = 1.0.0.0, kultūra = neutralus, PublicKeyToken = null“ arba viena iš jo priklausomybių. Sistema negali rasti nurodyto failo.

„KompilerLib“ yra „Windows“ klasės bibliotekos (3.5) projektas ir tai yra vienintelis failas projekte (viena sąsaja ir viena klasė).

Ar turiu ką nors daryti, jei naudoju „CodeDom.Compiler“ priede?

naudojant sistemą; naudojant System.Collections.Generic; naudojant System.Text; naudojant System.CodeDom.Compiler; naudojant System.Diagnostics; naudojant System.IO; vardų sritis KompilerLib {viešoji sąsaja IKalkulation {string Test (); } public class Kompiler {private const string TYPENAME = "Kalk.Kalkulation"; public IKalkulation Kompile (eilutės kalba, sąrašas nuorodos, eilutės šaltinis) {CodeDomProvider Provider = CodeDomProvider.CreateProvider (kalba); var parametrai = naujas CompilerParameters (); parametrai.GenerateInMemory = tiesa; parametrai.GenerateExecutable = false; foreach (eilutės nuoroda nuorodose) {parametrai.ReferencedAssemblies.Add (nuoroda); } var rezultatai = Provider.CompileAss AssemblyFromSource (parametrai, šaltinis); if (results.Errors == null || results.Errors.Count == 0) {Debug.Print (results.CompiledAssemble.ReflectionOnly.ToString ()); foreach (įveskite t rezultatuose. CompiledAssemble.GetTypes ()) Debug.Print (t.Name); var tipas = results.CompiledAssemble.GetType (TYPENAME); if (type == null) mesti naują išimtį ("tipas nerastas:" + TYPENAME); objektas o = Activator.CreateInstance (tipas); if (o == null) išmesti naują išimtį ("negaliu sukurti inscenizacijos"); var kalkulation = o kaip IKalkulation; if (kalkulation == null) mesti naują išimtį ("negali perduoti į IKalkulation"); grįžti kalkuliacija; } else {StringBuilder sb = new StringBuilder (); foreach (CompilerError klaida rezultatuose. Klaidos) sb.AppendLine (err.ErrorText); mesti naują išimtį (sb.ToString ()); }} public static string Test () {var kompiler = new Kompiler (); var sąrašas = naujas sąrašas(); list.Add ("System.dll"); eilutės kelias = kompiler.GetType (). Assembly.Location; if (! File.Exists (kelias)) išmeta naują Išimtį ("failas nerastas" + kelias); list.Add (kelias); eilutės šaltinis = GetSource (); var kalk = kompiler.Kompile ("CSharp", sąrašas, šaltinis); return kalk.Test (); } privati ​​statinė eilutė GetSource () {StringBuilder sb = new StringBuilder (); sb.AppendLine ("naudojant KompilerLib;"); sb.AppendLine ("vardų sritis Kalk"); sb.AppendLine ("{"); sb.AppendLine ("viešoji klasė Kalkulation: IKalkulation"); sb.AppendLine ("{"); sb.AppendLine ("viešas eilutės testas ()"); sb.AppendLine ("{"); sb.AppendLine ("return " Labas pasaulis ";"); sb.AppendLine ("}"); sb.AppendLine ("}"); sb.AppendLine ("}"); return sb.ToString (); }}}

Atnaujinti

Štai pataisymas naudojant „AssemblyResolve“ dėka „blah238“. Man vis dar įdomu, kodėl tai yra „arcmap.exe“ problema, bet ne mano konsolės testerio exe. Taip pat atrodo, kad lengviausia išspręsti surinkimą, kurį vykdo kompiliatorius.

public IKalkulation Kompile (eilutės kalba, sąrašas nuorodos, eilutės šaltinis) {CodeDomProvider Provider = CodeDomProvider.CreateProvider (kalba); var parametrai = naujas CompilerParameters (); parametrai.GenerateInMemory = tiesa; parametrai.GenerateExecutable = false; foreach (eilutės nuoroda nuorodose) {parametrai.ReferencedAssemblies.Add (nuoroda); } // tai tikrai atrodo kaip įsilaužimas ... AppDomain.CurrentDomain.AssembleResolve += (s, args) => {if (args.Name == this.GetType (). Assembly.FullName) grąžinkite this.GetType (). Assembly ; else return null; }; var rezultatai = teikėjas.CompileAssembleFromSource (parametrai, šaltinis); if (results.Errors == null || results.Errors.Count == 0) {var type = results.CompiledAssemble.GetType (TYPENAME); if (type == null) mesti naują išimtį ("tipas nerastas:" + TYPENAME); objektas o = Activator.CreateInstance (tipas); if (o == null) išmesti naują išimtį ("negaliu sukurti inscenizacijos"); var kalkulation = o kaip IKalkulation; if (kalkulation == null) mesti naują išimtį ("negali perduoti į IKalkulation"); grįžti kalkuliacija; } else {StringBuilder sb = new StringBuilder (); foreach (CompilerError klaida rezultatuose. Klaidos) sb.AppendLine (err.ErrorText); mesti naują išimtį (sb.ToString ()); }}

Naudodamas pasirinktinį .NET, susidūriau su panašiomis problemomisKonfigūracijos skyriusir kai naudojamas dvejetainis (de) serializavimas. Ši problema aptariama šio klausimo komentaruose: „ArcMap“ priedas su app.settings neatpažįsta app.config pakeitimų?

Atrodo, kad problema yra ta, kad kai kurių rinkinių, į kuriuos nurodo priedai, nepavyksta išspręsti teisingai, nes priedų programos domenas nėra atskirtas nuo pagrindinio programos domeno, todėl .NET vykdymo laikas atrodo pagrindinės programos surinkimo zondavimo kelyje ir jų neranda. Pataisymas yra naudoti Surinkimas. Pakrovimas ir tvarkyti „AppDomain.AssembleResolve“ įvykis.

Tai buvo pataisa, kuri man padėjo su paprotiuKonfigūracijos skyriussutrikimas. Tikiuosi, kad tai veiks ir jūsų atveju!