Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

[erledigt] Eingriff in Type.GetType zum Auflösen der korrekten Assembly
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

[erledigt] Eingriff in Type.GetType zum Auflösen der korrekten Assembly

beantworten | zitieren | melden

Hallo!

Ich habe mehrere Typen, nennen wir einen davon einmal T, deren Namen als typeof(T).FullName (um später wieder die Assembly, aus der sie stammen, rekonstruieren zu können - Name alleine reicht hier nicht) gespeichert werden. Via Type.GetType kann ich dann später Informationen über den gespeicherten Typnamen bekommen, Instanzen erzeugen etc. So weit, so gut, wenn sich Assemblyname und -version nicht ändern.
Ändert sich die Version der Assembly, schlägt das Auflösen des Namens zu einem Typ fehl. Wie ich herausgefunden habe, kann ich hier Abhilfe schaffen, falls es ein Typ ist, dessen dazugehörige Assembly ich schon zur Compilezeit kenne (kommt in meinem Anwendungsfall glücklicherweise oft vor, wenn Abhängigkeiten bereits geladen sind), indem ich auf das AssemblyRevolve-Ereignis der aktuellen AppDomain reagiere:

            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(delegate(object obj, ResolveEventArgs args) //React on assembly resolving errors on changing library versions
            {
                return Assembly.GetAssembly(typeof(EinTypTDerBekanntIst)); //Try the library's current assembly (version)
            });
Das klappt soweit. Mein aktuelles Problem: wenn ich meine Libraries und mein Hauptprogramm mit ILMerge zusammenfüge und mit der zusammengefügten Assembly z.B. den Typ MergedAssembly.T (als String) speichere, liefert Type.GetType beim Starten der Anwendung alleine (d.h. mit externen Libraries) zwar ohne Exception einen Typ, doch verweist dieser "ins Nichts", d.h. er hat nicht die richtigen Attribute, implementiert keine Schnittstellen etc. Gibt es irgendeine Möglichkeit, in Type.GetType über ein anderes Ereignis oder eine Einstellung so einzugreifen, dass ich der Runtime dazu bewegen kann, die aus meiner Sicht korrekte, d.h. aktuelle, Assembly aus meinen Abhängigkeiten zu verwenden, ohne dass der Assemblyname dabei gleich wie die im String sein muss?

Danke im Voraus für eure Hilfe
Grüße
Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
Blacal
myCSharp.de - Member



Dabei seit:
Beiträge: 392

beantworten | zitieren | melden

Hi,

zuerst mal muss ich sagen Hää...?
Ich versteh dein Problem ehrlich gesagt nicht so ganz, versuche aber trotzdem mal eine Antwort zu geben.

Ich frage mich gerade, wass das AssemblyResolve bei dir überhaupt für einen Sinn macht. Das Ereignis wird aufgerufen, wenn eine Assembly zu einem Typ nicht gefunden werden kann und bietet die möglichkeit, sie etwa aus einem anderen Pfad o. Ä. zu laden. Bei dir würde eigentlich dieses typeof(EinTypTDerBekanntIst) bereits das Laden der Assembly auslösen, und zwar der Assembly, in der EinTypTDerBekanntIst enthalten ist. Sollte das eine andere sein und du gaukelst der CLR vor, dass das die eigentlich gesuchte Assembly ist, und du kriegst Probleme später im Programm. Ich würde die Assembly nicht per Assembly.GetAssembly(typeof(...)) zurückgeben, sondern innerhalb des Ereignisses einfach die richtige Assembly laden (z. B. aus einer Datei per Assembly.LoadFile Methode).

Gruß
Roland
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Hallo!

Vielleicht habe ich mich zu kompliziert ausgedrückt. Ich gebe mal ein konkretes Beispiel: Die mit ILMerge zu M zusammengefügten Assemblies A (Anwendung) und L (Library) werden gestartet und ein Typname, Namespace.Test, als String gespeichert, d.h. z.B.
Zitat
Namespace.Test, M, Version=1.0.4467.38266, Culture=neutral, PublicKeyToken=null
Versuche ich nun, die Anwendung alleine zu starten, den String zu lesen und in einen Typ umzuwandeln (der sich in L befindet und zur Laufzeit geladen ist), wird nicht der richtige Typ gefunden. Selbst wenn ich den Loader zwinge, L zu verwenden, gibt er mir nicht den richtigen Typ zurück - warum, weiß ich nicht. Ich nehme an, dass es daran liegt, dass er obigen Typ sucht, aber den hier findet:
Zitat
Namespace.Test, L, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

Grüße
Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Dust Signs,

wenn ich dich richtig verstehe, würde es dein Problem lösen, wenn du ohne ILMerge arbeitest. Da das ohnehin das übliche Vorgehen ist, würde ich dir dazu raten.

Oder mit anderen Worten, dein Problem tritt nur auf, weil du dir das Leben mit dem ILMerge selbst unnötig schwer machst.

herbivore
private Nachricht | Beiträge des Benutzers
JuyJuka
myCSharp.de - Experte

Avatar #avatar-2316.jpg


Dabei seit:
Beiträge: 2282
Herkunft: Deutschland

beantworten | zitieren | melden

Hallo Dust Sings,

Das Thema gab es schon ein paar mal im Forum.
[erledigt] AssemblyResolve - einbinden dlls in die exe
Benutzer Programm generieren lassen
Entwurf eines eigenen Frameworks
...
(suche nach "netz dll")

Es gibt auch eine fertige Softwar die das kann (selber nie ausprobiert):
.Netz

Gruß
Juy Juka
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Danke für den Hinweis mit .NETZ. Ich werde das mal an Stelle von ILMerge versuchen.

Grüße
Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Hallo!

Ich habe .NETZ ausprobiert - danke für euren Hinweis. Es löst das Problem prinzipiell, schafft aber auch ein neues - die Berücksichtigung unterschiedlicher Versionen über das AssemblyResolve-Event funktioniert nun nicht mehr. Nach einigen Stunden des Debuggens habe ich herausgefunden, dass das AssemblyResolve-Event in den .NETZ-Executables gar nicht mehr aufgerufen wird. Damit ist die "Lösung" für mich keine wirkliche, da ich das Problem mit den unterschiedlichen Assembly-Versionen, das ich schon gelöst hatte, nun nicht mehr lösen kann. Oder gibt es irgendeinen Workaround dazu?

EDIT: Ich habe die Lösung gefunden: Die .NETZ-Executable listet manche Assemblies in AppDomain.CurrentDomain.GetAssemblies() doppelt. Sucht man anhand des Assembly-Namen die Assembly manuell in der o.g. Liste, wählt den zweiten Treffer (nicht den ersten), kann man mittels GefundeneAssembly.GetType(...) den richtigen Typ bekommen.

Grüße
Dust Signs
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Dust Signs am .
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
Blacal
myCSharp.de - Member



Dabei seit:
Beiträge: 392

beantworten | zitieren | melden

Hi,
Zitat
...Die .NETZ-Executable listet manche Assemblies in AppDomain.CurrentDomain.GetAssemblies() doppelt...

Ich würde dann aber mal genau überprüfen, ob im Programm noch alles so funktioniert, wie es soll. Glaub nicht, dass es ohne Folgen bleibt, wenn Assemblies doppelt geladen werden.

Gruß
Roland
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Hallo Roland!

Das Programm scheint soweit noch einwandfrei zu funktionieren. Soweit ich erkennen kann, ist momentan nur die "Haupt"-, d.h. Einsprungs-Assembly doppelt gelistet - einmal ohne Pfad mit dem den eigentlichen Klassen etc., und einmal mit Pfad und mit nur einer NETZ_0_4_8-Klasse (die wahrscheinlich für die Dekomprimierung und das Laden zuständig ist). Das scheint sonst nichts weiter zu beeinträchtigen.

Grüße
Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7559
Herkunft: Waidring

beantworten | zitieren | melden

Hallo Dust Signs,
Zitat
wählt den zweiten Treffer
wenn das nicht explizit so dokumentiert ist, so würde ich mich darauf nicht verlassen. Es kann zum einen nicht deterministisch sein, also die Reihenfolge willkürlich, und zum anderen könnte sich bei einem Update von NETZ diese Reihenfolge auch ändern.


mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Das mag sein, aber momentan ist das die einzige Lösung, die zuverlässig funktioniert. Mir wäre es auch lieber, wenn ich die Assembly-Auflösung nicht händisch und unter Zuhilfenahme dieser Beobachtungen bzgl. der Reihenfolge machen müsste, aber anders funktioniert es leider nicht.
Falls jemand Alternativen kennt, bitte immer her damit :)

Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10080

beantworten | zitieren | melden

Klar gibt es alternativen, aber die ( z.b. von herbivore ignorierte ) willst du nicht hören.

1. Warum gibt es einen String der eine andere Versionsnummer hat als die Assmbly?
2. Solltest Du mal das Prinzip dahinter verstanden haben, wäre doch eine Abfrage ohne Version zielführend.
3. Warum machst du diesen .. Überhaupt?
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Die Versionsnummer kodiert in meinem Anwendungsfall das Builddatum und wird daher zur Speicherung dieser Information verwendet. Die Struktur der Typen ändert sich über die Versionen hinweg nicht, weswegen ich die Version nicht überprüfen muss.
Zudem verstehe ich nicht, was du mit
Zitat
aber die ( z.b. von herbivore ignorierte ) willst du nicht hören
meinst: Ich habe ILMerge durch .NETZ ersetzt und bin nun dadurch auf andere Workarounds angewiesen, die ich oben beschrieben habe.

Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10080

beantworten | zitieren | melden

Nein, warum machst du das überhaupt.

1. Warum ILMerge oder Netz?
2. Warum benutzt du überhaupt die Versionsnummer, wenn die ( deinen Angaben nach ) doch sowieso obsolet ist?
private Nachricht | Beiträge des Benutzers
Dust Signs
myCSharp.de - Member



Dabei seit:
Beiträge: 95
Herkunft: Salzburg

Themenstarter:

beantworten | zitieren | melden

Zitat von FZelle
Nein, warum machst du das überhaupt.
Hauptsächlich benötige ich diese Information für einen eigenen Serializer, mit dem ich einige spezielle Anforderungen erfüllen muss, die mir weder die im Framework eingebauten noch die sonst verfügbaren Serializer erfüllen können.
Zitat von FZelle
1. Warum ILMerge oder Netz?
Am Schluss muss eine Assembly herauskommen. Diese Einschränkung stammt nicht von mir, sondern ist von außen vorgegeben.
Zitat von FZelle
2. Warum benutzt du überhaupt die Versionsnummer, wenn die ( deinen Angaben nach ) doch sowieso obsolet ist?
Auch das ist von außer vorgegeben.

Dust Signs
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
private Nachricht | Beiträge des Benutzers