2015-08-17 8 views
26

Mein Projekt (irgendeine Art von Verarbeitungsmodul) ist in zwei DLLs aufgeteilt: eines mit Schnittstellendeklarationen und eines mit Funktionalität. Normalerweise wird das Projekt von einem externen Delphi-Projekt über COM-Technologie verwendet.Wie kann ich meine DLL nur von Codebasis laden?

Lets sagen meine Programmscheiben Früchte. Externes Delphi-Programm erstellt ein Fruit-Objekt und füllt seine Eigenschaften: weight (int), Name (string) und ProgressUpdater (vom Typ IProgressUpdater, der in der zweiten dll mit Schnittstellen deklariert ist). Nach diesem exst-Programm creater Slicer, macht Slicer.AddFruit (newFruit) und ruft Slicer.Slice() auf.

Nichts besonderes. Im wirklichen Leben ist Delphi Project Outlook Addin. Aber hier ist das Problem - manchmal machen einige VSTO Addins Outlook funktioniert im "Schattenkopie-Dateien" -Modus, so wenn Delphi-Projekt startet und erstellt Slicer-Objekt, unsere C# -Assembly wird in Temp Ordner und Assembly wird mit diesem lokalen Pfad erstellt werden. Nun ... das ist immer noch kein Problem. Aber das Problem ist, wenn Delphi-Projekt newFruit erstellt und dann ProgressUpdater-Objekt übergibt, in meiner Slicer-Assembly kann ich nicht erhalten ProgressUpdater: "Return-Argument hat einen ungültigen Typ", aber immer noch Feld mit einfachen Typen (Gewicht, Name) erhalten.

Es tritt nur auf, wenn der Modus shadowCopyFiles aktiviert ist. Also meine Vermutung ist - externe ProgressUpdater Assembly und Slicer Assembly sind an verschiedenen Orten platziert, so dass sie nicht weitergegeben werden können. Meine Frage ist, wie man vermeidet, dass meine DLL "Schattenkopie" wird? Oder gibt es eine andere Lösung?

+1

Ich bin nicht sehr vertraut mit COM-Technologie, aber sollten nicht Baugruppen von GAC genommen werden? Wie [hier] (http://edn.embarcadero.com/article/32754) – netaholic

+1

Hmm, Sie sind das Opfer der fragwürdigen Praktiken eines anderen Addins. Sie können nicht viel tun, wenn Sie keine Telefonnummer haben. Aber eine Sache, benutze die GAC. Immer eine gute Idee, wenn Sie ComVisible Assemblies schreiben. –

+0

@HansPassant das Problem ist meine Baugruppe ist bereits in GAC registriert. Aber in einem Fall Assembly.GetExecutingAssembly(). Location; zeigt den Codebase-Pfad (den Pfad, in dem er bei regasm für COM interop registriert wurde). aber in einem anderen (nach diesem VSTO-Add-In) - einige Temp-Pfad auf Systemlaufwerk. Ich denke, dass ich solch ein Problem nicht haben werde, wenn ich .net zwingen kann, meine Versammlung nur vom Codebasisweg zu laden. – Shelest

Antwort

1

Also als Ergebnis habe ich immer noch keine Antwort für genaue Frage. Aber das Problem ist (dank HansPassant) durch die Verwendung von GAC gelöst, weil Assemblies bei GAC niemals Schatten-kopierte werden (Linker wird immer zuerst Assemblys in GAC und dann an anderen Orten testen).

Mögliche Antwort auf die Frage ist currentDomain.AssemblyResolve gehen, aber ich konnte diese Lösung nicht auf DLL anwenden, die nur öffentliche Schnittstellen (Typen) enthält. Vielleicht wird es für einige Fälle die passende Lösung sein.

1

Sie können Reflektion verwenden, um DLL dynamisch von einem beliebigen Speicherort zu laden. Wenn Sie diesen Weg gehen können, kann ich weiteren Code zum Laden von DLLs zur Verfügung stellen.

+0

Ja, bitte geben Sie ein Beispiel an. Meine Situation ist, dass meine DLL nur Schnittstellen (keine Methoden) enthält und von Delphi über COM verwendet wird. Wie kann ich garantieren, dass, wenn Guy auf Delphi MyComDll.IProgressUpdater ausführt, es von Codebase geladen wird? – Shelest

+0

@Shelest, um Baugruppe über Reflektion zu laden, können Sie etwas tun: Assembly.Load (File.ReadAllBytes (Pfad)) - nur einmal vor dem ersten Aufruf. Sie können auch meinen Artikel lesen: http://wojciechkulik.pl/csharp/embedded-class-libraries-dll (es geht um etwas anderes, aber vielleicht wird ein Teil davon nützlich sein). –

Verwandte Themen