Necesito ejecutar un método en un ensamblaje cargado durante el tiempo de ejecución. Ahora quiero descargar esos ensamblajes cargados después de la llamada al método. Sé que necesito un nuevo dominio de aplicación para poder descargar las bibliotecas. Pero aquí, el problema surge.Montaje de carga/descarga en diferentes AppDomain
Los ensambles que se van a cargar son complementos en mi marco de plugins. No tienen punto de entrada en absoluto. Lo único que sé es que contienen algunos tipos que implementan una interfaz determinada. El viejo, no dominio de aplicación de código tiene este aspecto (ligeramente abreviada):
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;
}
Ahora quiero que se carguen en un propio dominio de aplicación:
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);
}
Como se puede ver, he puesto en 5 casos
Si fijo el controlador de eventos, me sale una excepción que la asamblea (que es una consola de administración (mmc.exe) SnapIn. No se pudo encontrar/cargado.
ExecuteAssembly no encuentra una punto de entrada (bueno, no hay ninguno).
no tengo idea de cómo el tipo se llama. la forma de cargar por la interfaz?
similares a 3. ¿Cómo obtener el nombre de un montaje?
mismo error que en 1.
creo que el problema podría ser la consola de gerencia de alguna manera o tengo simplemente ni idea de lo que estoy haciendo mal. Cualquier ayuda es apreciada.
ACTUALIZA 1
ahora han intentado usar la solución de proxy publicado.
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...
}
}
Esto tampoco funciona. Al tratar de crear el objeto proxy, recibo una excepción:
No se pudo cargar el archivo o ensamblado 'MyProject.SnapIn, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null' o una de sus dependencias. El sistema no puede encontrar el archivo especificado.
El archivo en el mensaje de error es el que está cargado en mmc (el SnapIn). ¿Alguna idea de cómo solucionar este error? AppDomain.AssemblyResolve no se llama (ni en el dominio antiguo ni en el nuevo).
ACTUALIZACIÓN 2
ahora han intentado la solución con el AppDomainSetup. Ahora, la excepción ha cambiado a:
No se pudo cargar el archivo o ensamblado 'file: /// C: /Development/MyProject/bin/SnapIn/MyProject.SnapIn.DLL' o una de sus dependencias. El nombre de ensamblado dado o base de código no es válido. (Excepción de HRESULT: 0x80131047)
¿Alguna idea?
¿Ha tratado de crear una clase que hereda de MarshallByRef para actuar como apoderado y dejar que haga ese trabajo sucio en el nuevo contexto de dominio de aplicación? –
¿Estaría esta clase en el ensamblaje para cargar o en el ensamblaje ya cargado (el que intenta cargar los otros)? – Scoregraphic
por favor, vea mi respuesta a continuación –