Mein Ziel: Ich schreibe eine vsix (Visual Studio-Erweiterung), wo ich ein Projekt kompilieren möchte, laden Sie dann die resultierende DLL und überprüfen Sie es durch Reflexion. Aufgrund der Art, wie der Code geschrieben wird, kann ich ReflectionOnlyLoad()
nicht verwenden. Wenn ich einfach Assembly.Load
mache, dann ist die Datei gesperrt, bis der Benutzer die gesamte IDE neu startet.Assembly.LoadFrom() oder Assembly.Load() kann Datei löschen
Ich versuche, eine separate AppDomain basierend auf den Beispielen, die ich online gefunden habe, einzurichten.
Der Kern ist: 1. ich einen Proxy-Klasse erstellt, die die Daten über AppDomain
Instanzen Marschall würde:
internal class AppDomainProxy : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
return Assembly.LoadFile(assemblyPath);
}
}
ich dann eine Instanz davon: Dieses
var domaininfo = new AppDomainSetup { ApplicationBase = System.Environment.CurrentDirectory, ShadowCopyDirectories = "true", ShadowCopyFiles = "true", LoaderOptimization = LoaderOptimization.MultiDomainHost };
var adevidence = System.AppDomain.CurrentDomain.Evidence;
var domain = System.AppDomain.CreateDomain("reflection", adevidence, domaininfo);
var proxyType = new AppDomainProxy().GetType();
var proxyInstance = (AppDomainProxy)domain.CreateInstanceFromAndUnwrap(proxyType.Assembly.Location, proxyType.FullName);
var loadedAssembly = (proxyInstance as AppDomainProxy).GetAssembly(this._assemblyLocation);
kann meinen transparenten Proxy nicht an meinen Typ übertragen. Um dies zu umgehen, kann man leicht eine Baugruppe Resolver wie so liefern:
this.domain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
private Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
var loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in loadedAssemblies)
{
if (assembly.FullName == args.Name)
{
return assembly;
}
}
return null;
}
Dies funktioniert gut, mein Proxy gegossen wird. Wenn ich jedoch meine Methode aufrufen, wird die CurrentDomainOnAssemblyResolve
erneut aufgerufen, was darauf hindeutet, dass Assembly
Eigenschaft ist nicht wirklich serialisierbar und so. NET versucht einfach die Assembly auf der ursprünglichen Seite zu laden, so dass das gleiche Problem wie Assembly.Load
. Das ist leicht zu sehen, weil einfache Microsoft-Beispiele wie gut funktionieren.
UPDATE Zur Umgehung des Problems Ich zog mein Code, der die Montage benötigt auf der anderen Seite (innerhalb der Domäne) laufen und dann die Zeichenfolge wieder zurück, die feinen Marschälle. Ich werde die Frage jedoch offen halten, weil ich wissen möchte, ob es eine Lösung für das eigentliche Problem gibt.
Nun, Sie sind wieder auf Platz eins wieder, weil die Assembly jetzt in _both_ AppDomains geladen ist und Sie nur 'Unload()' einer von ihnen. Warum nicht alles tun, was in Ihrer sekundären AppDomain getan werden muss? – MickyD
@MickyD Nach dem Update auf die Frage, das ist, was ich getan habe. Aber ich mag es nicht:/ – zaitsman
Mag es nicht? Das ist der ganze Sinn von AppDomains. Das Erstellen einer Appdomain zum Isolieren zum Laden einer Assembly oder eines Plugins, nur um sie an die übergeordnete Domäne zurückzugeben, widerspricht genau dem Zweck von Sandboxes, wenn Sie ein untergeordnetes Thread erstellen, um eine langwierige Task auszuführen, aber nur auf die Beendigung warten . Es gibt einige gute Artikel, die ich Ihnen im MSDN Magazin für App-Domains empfohlen habe. – MickyD