2011-06-27 10 views
6

he creado una biblioteca de pruebacopia sombra con el fin de no bloquear el montaje

public class Test 
{ 
    public int Add(int val1, int val2) 
    { 
     return val1 + val2; 
    } 
} 

y un proyecto para llamarlo:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      String path = @"...Lib.dll"; // path to lib 
      var name = Path.GetFileName(path); 

      AppDomainSetup setup = new AppDomainSetup 
      { 
       ApplicationBase = @"...", // directory where Lib.dll is 
       ShadowCopyFiles = "true", 
       ShadowCopyDirectories = @"..."// directory where Lib.dll is 
      }; 

      var appdomain = AppDomain.CreateDomain("Loader." + name, null, setup); 
      Assembly ass = Assembly.LoadFile(path); // <--- I think here is the problem, here where assembly is locked 
      Assembly assembly = appdomain.Load(ass.FullName); 

      dynamic a = assembly.CreateInstance("Lib.Test"); 

      Console.WriteLine(a.Add(1, 5)); 
     } 
    } 
} 

Por favor, ayuda para encontrar lo que he hecho mal? ¿Por qué mi ensamblaje está bloqueado?

EDIT: con el nombre codificado de montaje:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomainSetup ads = new AppDomainSetup(); 

      String fullPath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"; 

      ads.ShadowCopyFiles = "true"; 
      ads.ApplicationName = "AppName"; 
      ads.ShadowCopyDirectories = Path.GetDirectoryName(fullPath); 
      //ads.ApplicationBase = Path.GetDirectoryName(fullPath); 
      //ads.PrivateBinPath = Path.GetDirectoryName(fullPath); 
      ads.CachePath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Cache\"; 

      AppDomain ad = AppDomain.CreateDomain("myName" + ads.ApplicationName, null, ads); 

      ad.AssemblyResolve += new ResolveEventHandler(ad_AssemblyResolve); 

      Console.WriteLine(ad.ShadowCopyFiles); 
      Console.WriteLine(ad.SetupInformation.ShadowCopyDirectories); 

      try 
      { 
       //Assembly assembly = ad.Load(AssemblyName.GetAssemblyName(fullPath)); 
       //dynamic obj = ad.CreateInstanceAndUnwrap(assembly.GetName().Name, "Lib.Test"); 

       dynamic obj = ad.CreateInstanceAndUnwrap("Lib", "Lib.Test"); 

       Console.WriteLine(obj.Add(1, 7)); 

       Console.ReadKey(); 

       Console.WriteLine(obj.Add(1, 90)); 
      } 
      catch(Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 

     static Assembly ad_AssemblyResolve(object sender, ResolveEventArgs args) 
     { 
      return Assembly.LoadFile(@"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"); 
     } 
    } 
} 

Es interesante que almacena en caché assebly también está bloqueado.

EDIT 2:

Aquí está la línea de código para bloquear el conjunto de

Console.WriteLine(obj.Add(1, 7)); 

Así que una vez un método en el Lib.Test se accede a la assenbly está bloqueado.

¿Cuál puede ser la solución?

+0

Por favor, publique el error exacto que está recibiendo. –

+0

El problema exacto como he dicho es que Lib.dll el ensamblaje está bloqueado. Por ejemplo, no puedo replicarlo una vez que se ejecuta la aplicación. – NDeveloper

+0

Debe usar una interfaz en un tercer ensamblaje para evitar que su código cargue el tipo construido en el dominio principal de la aplicación. No use LoadFile. –

Respuesta

0

Tiene dos opciones, necesita buscar el nombre del ensamblado antes de la ejecución y tenerlo codificado, o si no conoce el tiempo de ejecución anterior, necesita escribir una segunda biblioteca que conozca el FullName y cargar eso en AppDomain. La segunda biblioteca será una clase que tiene una función

public Assembly GetAssemblyForOtherAppDomain(string path) 
{ 
    return Assembly.LoadFile(path) 
} 

Esto debe cargar su objetivo en el nuevo dominio de aplicación sin bloquearlo como debe abrirlo con una instantánea.

EDIT: por qué su método no funcionó, que en razón de que la carga de bloqueo y once a assembly is loaded in to a AppDomain it can not be unloaded.

+0

Por supuesto que sé el nombre del ensamblado ... pero no lo hará ayuda. Lo he intentado ... el mismo problema. – NDeveloper

+0

Por favor, verifique la pregunta actualizada con el nuevo código. – NDeveloper

1

va a cargar el conjunto en su dominio de aplicación principal cuando se ejecuta Assembly.LoadFile(), que bloquea el archivo. Si desea cargarlo directamente en su AppDomain, necesita usar AppDomain.Load() directamente, permitiendo que AppDomain lo resuelva en función de los parámetros que haya especificado. Tenga en cuenta que, dado que el ensamblado no está cargado en su AppDomain principal, ese tipo es inaccesible desde su método Principal. Su Lib.Test tendrá que derivar de MarshalByRefObject para que el sistema de clasificación puede crear un proxy (que más se envuelve en un proxy dinámico cuando se asigna a dinámica.)


EDIT:

A Pensándolo bien, sospecho que el problema aquí es que, para llamar al método en el proxy dinámico, tiene que Reflexionar sobre el objeto (que es en sí mismo un proxy transparente para la instancia en su otro AppDomain). Si termina reflejando sobre el tipo de clase original (y no el tipo de proxy transparente "oculto"), esto hará que cargue una copia del ensamblado en el dominio de aplicación local (lo que lo bloquea). Esta es una de las razones por las que, al usar AppDomain isolat Por lo general, emite el objeto a una interfaz definida en un ensamblaje separado al que pueden hacer referencia tanto la aplicación 'principal' como el dominio de aplicación alojado. Cada uno de ellos obtendrá su propia copia del conjunto de interfaz cargada, pero ahora el ensamblaje de 'implementación' está aislado.

+0

Consulte el código editado ... no hay Assembly.LoadFile. También obtuve Lib.Test de MarshalByRefObject y configuré [Serializable], pero igual ... No puedo imaginarme qué hacer. – NDeveloper

+0

@NDeveloper, en este caso nuevo, está forzando a AppDomain a resolver el ensamblado llamando a LoadFile, que omite la copia oculta y carga el archivo directamente. Si desea que cargue el archivo utilizando el mecanismo de copia oculta, debe pasar el Nombre completo del ensamblado a CreateInstanceAndUnwrap y permitir que AppDomain haga su propia resolución de archivo. –

+0

Pero ad_AssemblyResolve nunca se llamó, por lo que todo lo que ha descrito. – NDeveloper

Cuestiones relacionadas