Moin zusammen,
Ich habe die Auflösung von Dependencies (Assemblies) in meinem Projekt scheinbar so gut optimiert, dass sie zwar super schnell ist, allerdings dafür auch (scheinbar) nicht immer alle Assemblies in die Applikation lädt.
Nun stehe ich zugegebenermaßen etwas auf dem Schlauch und sehe wahrscheinlich den Wald vor lauter Bäume nicht mehr.
Etwas zum Hintergrund:
Die Applikation ist hochmodular aufgebaut und kann zur Laufzeit Module ein-/entladen. Die Dependencies können allerdings in mehreren Ordnern zerstreut sein (ergibt sich leider aus den Abhängigkeiten zu IKVM und div. weiteren Sachen), sodass der Default-Resolver oftmals die benötigte Binary gar nicht findet und stattdessen die Applikation stirbt.
Im Spoiler findet ihr den aktuellen Quellcode.
Spoiler anzeigen
Was mich dabei gerade wundert, ist folgendes:
Sowohl durchs Besichtigen der Logmeldungen, als auch beim Durchsteppen der Anwendung kann ich sehen, dass die erforderlichen Bibliotheken gefunden und geladen(!) werden.
Allerdings kommt dennoch folgender Fehler:
Vielleicht seht ihr ja, wo ich das verbaselt habe.
EDIT: Um zu bestätigen, dass ich tatsächlich (trotz doppelter und dreifacher Prüfung) die richtige DLL lade, habe ich das Ding fix dekompiliert:
Elastic.Transport.Dll enthält die NodePool.
Und Elastic.Clients.Elasticsearch.dll enthält auch den nicht gefundenen Constructor.
Ich habe die Auflösung von Dependencies (Assemblies) in meinem Projekt scheinbar so gut optimiert, dass sie zwar super schnell ist, allerdings dafür auch (scheinbar) nicht immer alle Assemblies in die Applikation lädt.
Nun stehe ich zugegebenermaßen etwas auf dem Schlauch und sehe wahrscheinlich den Wald vor lauter Bäume nicht mehr.
Etwas zum Hintergrund:
Die Applikation ist hochmodular aufgebaut und kann zur Laufzeit Module ein-/entladen. Die Dependencies können allerdings in mehreren Ordnern zerstreut sein (ergibt sich leider aus den Abhängigkeiten zu IKVM und div. weiteren Sachen), sodass der Default-Resolver oftmals die benötigte Binary gar nicht findet und stattdessen die Applikation stirbt.
Im Spoiler findet ihr den aktuellen Quellcode.
C#-Quellcode
- private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) {
- ArgumentNullException.ThrowIfNull(sender);
- var folderPath = Path.GetDirectoryName(args.RequestingAssembly?.Location);
- if (string.IsNullOrEmpty(folderPath)) {
- folderPath = ConfigManager.Instance.GetPluginInstallDir().FullName;
- }
- var asmName = new AssemblyName(args.Name);
- if (folderPath is null || asmName.Name is null) {
- AppLogger?.Error("Could not find assembly {asmName} in {location}! Requested by {requesting}", asmName.Name, folderPath, args.RequestingAssembly?.GetName().Name);
- return default;
- }
- var loadDirInfo = new DirectoryInfo(folderPath);
- var rawPath = Path.Combine(folderPath, asmName.Name);
- var asmPath = rawPath + ".dll";
- Assembly? loadedAsm = default;
- if (!File.Exists(asmPath)) {
- AppLogger?.Warning("Could not find {asmPath}! Attempting brute-force load. This might take a while!", asmPath);
- foreach (var file in loadDirInfo.GetFiles().Where(f => f.Extension.ToLower().Equals(".dll", StringComparison.InvariantCultureIgnoreCase))) {
- if (file.Name.Contains(asmName.Name)) {
- loadedAsm = Assembly.Load(File.ReadAllBytes(file.FullName));
- break;
- }
- var stringContent = new string(File.ReadAllText(file.FullName).Where(c => char.IsAscii(c) || char.IsAsciiDigit(c) || char.IsWhiteSpace(c)).ToArray());
- if (stringContent.Contains(asmName.Name)) {
- loadedAsm = Assembly.Load(File.ReadAllBytes(file.FullName));
- if (loadedAsm.GetName().GetPublicKeyToken().SequenceEqual(asmName.GetPublicKeyToken())) {
- break;
- }
- }
- }
- goto Failure; // ignoriert mich, ich habe einen Sinn
- } else {
- loadedAsm = Assembly.Load(File.ReadAllBytes(asmPath));
- }
- return loadedAsm;
- Failure:
- AppLogger?.Error($"Failed to resolve assembly {args.Name}. Hermod may not work as expected.");
- return default;
- }
Was mich dabei gerade wundert, ist folgendes:
Sowohl durchs Besichtigen der Logmeldungen, als auch beim Durchsteppen der Anwendung kann ich sehen, dass die erforderlichen Bibliotheken gefunden und geladen(!) werden.
Allerdings kommt dennoch folgender Fehler:
Quellcode
- [21:09:13 DBG] [EmailIndexer] Initialising elasticsearch handler...
- [21:09:13 INF] [EmailIndexer] Connecting to and retrieving info from Elastic cluster...
- [21:09:14 ERR] [EmailIndexer] Failed to connect to Elasticsearch cluster! Error: Method not found: 'Void Elastic.Clients.Elasticsearch.ElasticsearchClientSettings..ctor(Elastic.Transport.NodePool)'.
Vielleicht seht ihr ja, wo ich das verbaselt habe.
EDIT: Um zu bestätigen, dass ich tatsächlich (trotz doppelter und dreifacher Prüfung) die richtige DLL lade, habe ich das Ding fix dekompiliert:
Elastic.Transport.Dll enthält die NodePool.
Und Elastic.Clients.Elasticsearch.dll enthält auch den nicht gefundenen Constructor.
Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)
Meine Firma: Procyon Systems
Selbstständiger Softwareentwickler & IT-Techniker.
Meine Firma: Procyon Systems
Selbstständiger Softwareentwickler & IT-Techniker.
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „siycah“ ()