Ładowanie / rozładowywanie zespołu w innej domenie aplikacji
Muszę wykonać metodę w zespole załadowanym podczas wykonywania. Teraz chcę usunąć te załadowane zestawy po wywołaniu metody. Wiem, że potrzebuję nowej domeny aplikacji, abym mógł rozładować biblioteki. Ale tutaj pojawia się problem.
Zgromadzone ładunki są wtyczkami w mojej strukturze wtyczek. Nie mają żadnego punktu wejścia. Wiem tylko, że zawierają niektóre typy implementujące dany interfejs. Stary, inny niż AppDomain kod wygląda tak (nieznacznie skrócony):
try
{
string path = Path.GetFullPath("C:\library.dll");
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Assembly asm = Assembly.LoadFrom(path);
Type[] types = asm.GetExportedTypes();
foreach (Type t in types)
{
if ((t.GetInterface("IStarter") != null) && !t.IsAbstract)
{
object tempObj = Activator.CreateInstance(t);
MethodInfo info = t.GetMethod("GetParameters");
if (info != null)
{
return info.Invoke(tempObj, null) as string;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.StartsWith("MyProject.View,"))
{
string path = Path.GetFullPath("C:\view.dll"));
return Assembly.LoadFrom(path);
}
return null;
}
Teraz chcę, aby załadowały się do własnej domeny aplikacji:
try
{
string path = Path.GetFullPath("C:\library.dll");
AppDomain domain = AppDomain.CreateDomain("TempDomain");
domain.AssemblyResolve += CurrentDomain_AssemblyResolve; // 1. Exception here!!
domain.ExecuteAssembly(path); // 2. Exception here!!
domain.CreateInstanceFrom(...); // 3. I have NO clue, how the type is named.
domain.Load(...); // 4. I have NO clue, how the assembly is named.
domain.DoCallBack(...); // 5. Exception here!!
// ...
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Jak widać, umieściłem 5 przypadków.
Jeśli ustawię procedurę obsługi zdarzeń, otrzymam wyjątek, że nie można znaleźć / załadować zespołu (jest to konsola zarządzania (mmc.exe).
ExecuteAssembly nie znajduje punktu wejścia (cóż, nie ma żadnego).
Nie mam pojęcia, jak nazywa się ten typ. Jak ładować przez interfejs?
Podobny do 3. Jak uzyskać nazwę zespołu?
Ten sam błąd co w 1.
Myślę, że problemem może być konsola zarządzania, albo nie mam pojęcia, co robię źle. Każda pomoc jest doceniana.
AKTUALIZACJA 1
Próbowałem teraz użyć wysłanego rozwiązania proxy.
AppDomain domain = AppDomain.CreateDomain("TempDomain");
InstanceProxy proxy = domain.CreateInstanceAndUnwrap(Assembly.GetAssembly(
typeof(InstanceProxy)).FullName, typeof(InstanceProxy).ToString()) as InstanceProxy;
if (proxy != null)
{
proxy.LoadAssembly(path);
}
AppDomain.Unload(domain);
public class InstanceProxy : MarshalByRefObject
{
public void LoadAssembly(string path)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Assembly asm = Assembly.LoadFrom(path);
Type[] types = asm.GetExportedTypes();
// ...see above...
}
}
To też nie działa. Podczas próby utworzenia obiektu proxy otrzymuję wyjątek:
Nie można załadować pliku lub zespołu „MyProject.SnapIn, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null” lub jednej z jego zależności. System nie może odnaleźć określonego pliku.Plik w komunikacie o błędzie jest załadowany do mmc (SnapIn). Masz pomysł, jak naprawić ten błąd? AppDomain.AssemblyResolve nie jest wywoływany (ani w starej ani w nowej domenie).
AKTUALIZACJA 2
Spróbowałem teraz rozwiązania z AppDomainSetup. Teraz wyjątek zmienił się na:
Could not load file or assembly 'file: /// C: /Development/MyProject/bin/SnapIn/MyProject.SnapIn.DLL ”lub jedną z jego zależności. Podana nazwa zespołu lub podstawa kodu była niepoprawna. (Wyjątek od HRESULT: 0x80131047)Dowolny pomysł?