2011-08-05 16 views
6

Tengo un marco que consta de muchas clases base que se pueden derivar para desarrollar muchas aplicaciones. Entre estas clases hay una subclase de System.Windows.Forms.Panel para la cual escribí su propio diseñador. Todo está funcionando bien con Visual Studio 2005, pero algo va mal cuando intento pasar a VS2010. Esta es una versión muy simplificada de lo que estoy haciendo:¿Dónde busca Visual Studio ensamblajes?

Tengo un proyecto llamado CoreClasse que contiene una interfaz y dos clases:

public interface IConf 
{ 
    string foo { get; set; } 
    void InitFoo(); 
} 

public class SimpleClass 
{ 
    public string foo; 
} 

public class ConfLoader 
{ 
    public static IConf LoadConf() 
    { 
     AssemblyName anAssemblyName = new AssemblyName("ConfClasses"); 
     Assembly anAssembly = Assembly.Load(anAssemblyName); 
     IConf result = (IConf)anAssembly.CreateInstance("ConfClasses.ConfClass"); 
     result.InitFoo(); 
     return result; 
    } 
} 

entonces hay una ConfClasses proyecto que hace referencia a CoreClasses y contiene sólo una iConf clase de aplicación:

public class ConfClass : IConf 
{ 
    public SimpleClass confVal; 

    public string foo 
    { 
     get { return confVal.foo; } 
     set { confVal.foo = value; } 
    } 

    public void InitFoo() 
    { 
     confVal = new SimpleClass(); 
     confVal.foo = "bar"; 
    } 
} 

y por último hay un proyecto para los controles que hace referencia sólo CoreClasses y contiene una subclase de Panel y el diseñador asociado:

[Designer("MyControls.Design.SimplePanelDesigner", typeof(IRootDesigner))] 
public class SimplePanel : Panel 
{ 
    public SimpleClass dummy = new SimpleClass(); 
} 

public class SimplePanelDesigner : DocumentDesigner 
{ 
    public IConf DesignerConf; 

    public SimplePanelDesigner() 
     : base() 
    { 
     DesignerConf = ConfLoader.LoadConf(); 
    } 
} 

Ahora creo otra solución que hace referencia a todos estos dlls y contiene una subclase vacía de SimplePanel. Cuando hago doble clic en esta clase en SolutionExplorer, se ejecuta el constructor de SimplePanelDesigner y se llama al método LoadConf de ConfLoader. Esto significa que ConfClasses.dll se carga dinamicamente y se crea una instancia de ConfClass. Todo está bien hasta este momento, pero cuando se llama a InitFoo se produce esta excepción:

No se pudo cargar el archivo o ensamblado 'CoreClasses, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null' o uno de sus dependencias. El sistema no puede encontrar el archivo especificado.

Para hacer las cosas más difíciles, la excepción no se plantea realmente en este ejemplo, pero este es exactamente el tipo de instrucciones que está ejecutando mi aplicación real, y la excepción que recibo. No tengo ni idea de lo que está sucediendo aquí. VS está ejecutando un método que está en CoreClasses. ¿Por qué está tratando de cargarlo de nuevo? ¿Y dónde lo está buscando? También revisé el dominio de aplicación actual, pero tiene CoreClasses entre sus ensamblados cargados, y no parece cambiar.

Solo para añadir más detalles, cada proyecto se compila en una carpeta común (no en la carpeta habitual obj/debug dentro de la carpeta del proyecto), y no hay otra copia de mis dlls en la PC en el momento en que empiezo mi prueba. A continuación, una copia de todos los dlls referenciados se realiza en una serie de carpetas en la carpeta AppData \ Local \ Microsoft \ VisualStudio \ 10.0 \ ProjectAssemblies de mi perfil de usuario, y este parece ser el lugar donde VS está buscando los ensamblados cuando Assembly.Load se ejecuta, y puedo encontrar una copia de CoreClasses allí. Traté de limpiar todas las carpetas, reconstruir todo y mantener las diferentes soluciones abiertas/cerradas en cada combinación, pero sin ninguna mejora.

EDIT:

Como sugirió GranMasterFlush, este es el FusionLog generada por la excepción:

=== Pre-bind state information === 
LOG: User = FCDB\fc0107 
LOG: DisplayName = XEngine.Core, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null (Fully-specified) 
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE/ 
LOG: Initial PrivatePath = NULL 
Calling assembly : (Unknown). 
=== 
LOG: This bind starts in default load context. 
LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe.Config 
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. 
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). 
LOG: The same bind was seen before, and was failed with hr = 0x80070002. 
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002). 

EDIT 2

sólo para añadir algo de información, me tomó un vistazo a los registros de fusión generado por mi ejemplo simple y descubrí que exactamente se ha generado el mismo registro al intentar cargar CoreClasses, pero de alguna manera VisualStudio encuentra una manera de lidiar con él.

+0

Utilicé [procmon] (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) para verificar que el archivo del que se quejaba realmente se encontraba en 'AppData \ Local \ Microsoft \ VisualStudio \ 11.0 \ ProjectAssemblies \ '. Al final fue porque mi control personalizado estaba tratando de iniciar un hilo (la propiedad 'DesignMode' no funciona, vea [esta solución] (http://stackoverflow.com/questions/39648/good-way-to-debug) -visual-studio-designer-errors)). Encontré esto pasando por [este artículo] (http://msdn.microsoft.com/en-us/library/ms996457.aspx) sobre cómo depurar el comportamiento del tiempo de diseño. – pelesl

Respuesta

4

Acabo de descubrir qué está pasando. La diferencia entre el ejemplo simple y el real es el hecho de que hay un AddIn involucrado. Es toda una historia de registro, pero esto es todo.
Como puede ver en el ejemplo del código, cargo el DLL de ConfClasses por reflexión para evitar agregar una referencia al mismo. Esto está bien en tiempo de ejecución, pero el diseñador se queja diciendo que no puede convertir IConf a IConf. Esto sucede porque CoreClasses.dll se carga desde AppData \ Local \ Microsoft \ VisualStudio \ 10.0 \ ProjectAssemblies cuando se inicia el diseñador, pero se carga ConfClasses.dll desde mi carpeta bin y también sus referencias, por lo que hay dos versiones de CoreClasses.dll y diferentes versiones de IConf.
Para eludir el problema desarrollé un AddIn que, cuando un ensamblaje se carga con Assembly.Load en el momento del diseño, agrega una referencia a ese ensamblaje y luego limpia las referencias cuando se cierra la última ventana del diseñador.
Todo estaba bien con VS2005, pero al usar ProcMon.exe descubrí que VS2010 agregaba una nueva carpeta donde los complementos buscaban ensamblajes: Archivos de programa (x86) \ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ CommonExtensions \ DataDesign
He copiado mi ensamblaje allí y todo funciona nuevamente. Ahora solo es cuestión de encontrar una forma de agregar cosas ahí manualmente.

2

¿Ha intentado utilizar el Visor de registro de encuadernación para investigar por qué esta falla al cargar los ensamblajes?

http://msdn.microsoft.com/en-us/library/e74a18c4%28v=vs.71%29.aspx

Hay otro artículo aquí acerca de su uso:

http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57120.aspx

EDIT:

donde se almacenan de la DLL? Este forum post detalla un problema similar y el problema se debe a que se hace referencia a la DLL que no está en el GAC, directorio ejecutable o una subcarpeta del directorio ejecutable:

+0

Agregué el FusionLog a la pregunta, pero no tiene mucho sentido para mí ... –

+0

Todos mis proyectos tienen una sola carpeta configurada como Ruta de salida, por lo que todos los dlls están en la misma carpeta, que obviamente no es la uno de Visual Studio. Los ensamblados no se cargan desde esta carpeta, sino desde una copia que se crea en subcarpetas de AppData \ Local \ Microsoft \ VisualStudio \ 10.0 \ ProjectAssemblies, y aquí puedo encontrarlos todos. –

Cuestiones relacionadas