Como yo lo entiendo, que quiere hacer lo siguiente:
- carga un ensamblado de disco, en la memoria, para usar datos en él o llamar al código
- Poder descargar el conjunto más adelante
- Evite bloquear el ensamblaje en el disco, para que pueda modificarlo sin tener que salir de la aplicación (o descargar el montaje primero)
Básicamente, lo que está describiendo es un tipo de sistema de complemento, y puede hacerlo con el uso de dll sombreados y dominios de aplicación.
Primero, para descargar un ensamblaje, sin simplemente salir de la aplicación, debe cargar ese ensamblaje en un dominio de aplicación separado. Debería poder encontrar buenos tutoriales en la red sobre cómo hacerlo.
Aquí hay un Google query que debería proporcionarle algunos artículos iniciales.
En segundo lugar, para evitar bloquear el conjunto en el disco, es simple, simplemente haga una copia primero y cargue la copia en lugar del original. Claro, bloquearás la copia, pero la copia es solo un archivo temporal para tu aplicación, por lo que nadie debería estar interesado en modificar ese archivo de todos modos. Esto deja el archivo original desbloqueado y modificable.
Debe intentar utilizar el sombreado en lugar de utilizar las sobrecargas de Assembly.Load
que pueden cargar ensamblajes de una matriz de bytes si tiene más de un ensamblaje que se cargará y reemplazará.
Por ejemplo, si su complemento A.dll se basa en un segundo conjunto B.dll, y utiliza el truco de matriz de bytes para cargar A.dll en la memoria antes de llamar a Assembly.Load, necesita manejar la resolución del conjunto llama al dominio de su aplicación (se le puede decir cada vez que se necesita cargar un ensamblaje y "ayuda" al proceso de carga), o necesita asegurarse de que B.dll se cargue primero de la misma manera que se carga A.dll; de lo contrario, cargue A.dll de la memoria cargará automáticamente B.dll del disco.
Aquí hay más información sobre el uso de dominios de aplicación separados.
Cuando se crea otro dominio de aplicación, a través del uso de la clase AppDomain en .NET, que está creando un compartimiento separado en la memoria donde se puede ejecutar código. Está realmente separado de su dominio de aplicación principal y solo tiene un pequeño orificio a través de la pared que los separa.
A través de este agujero puede pasar mensajes, como llamadas de método y datos.
Después de construir el nuevo dominio de aplicación, carga uno o más ensamblajes dentro de él. Normalmente cargará 1 si el conjunto que desea cargar ha sido creado para este tipo de carga, o 2 si no lo ha hecho (más sobre esto más abajo).
Después de cargar el conjunto, construye uno o más objetos dentro de ese otro dominio de aplicación, de forma que el primer dominio de aplicación pueda hablar con esos objetos. Estos objetos deben descender desde MarshalByRefObject, que es una clase que permite que ocurra algo de magia.
Básicamente lo que ocurre es lo siguiente. Dentro de ese otro dominio de aplicación, se crea un objeto de un tipo cargado en ese dominio de aplicación. Este tipo desciende de MarshalByRefObject. La solicitud para construir este objeto provino del primer dominio de aplicación, y dentro de este dominio de aplicación, se construye un objeto proxy, que se parece, pero no es, el mismo objeto que se creó en ese otro dominio de aplicación. El proxy habla con ese otro objeto, a través de ese agujero.
Ahora tiene dos dominios de aplicación y dos objetos, uno a cada lado, y los objetos se comunican entre sí.
Con esta configuración, más adelante puede cortar la conexión entre los objetos y luego descargar ese otro dominio de aplicación, que básicamente destruye ese compartimiento. Luego, si lo desea, puede construir un nuevo dominio de segunda aplicación y comenzar de nuevo, de hecho, volver a cargar los ensamblados desde el disco.
Una cosa a tener en cuenta es la información que se pasa por este agujero. Si alguno de los datos que pasan a través de ese agujero es un objeto que se declara en la asamblea que ha cargado (el plugin o conjunto de extensión), entonces no sólo va a conseguir ese objeto nuevo en su dominio principal de la aplicación, su dominio principal de la aplicación también cargue ese ensamblaje en su propio dominio y, por lo tanto, impida hablar correctamente con su segundo dominio de aplicación después de una recarga.
Así que asegúrese de no hacer eso, pase tipos nativos o tipos que están definidos fuera de los ensamblajes que desea reemplazar.
he mencionado que es posible que desee cargar al menos dos conjuntos. El razonamiento detrás de esto es que si el tipo que se desea construir, el tipo que se declara en ese ensamblado que desea cargar, no desciende de MarshalByRefObject, entonces surge nuevamente el problema de pasar tipos a través de ese agujero, y también cargarás el ensamblado en tu dominio principal. Una forma típica de manejar esto es tener algún tipo de plugin de clase gerente, que no descienden de MarshalByRefObject, y tienen este gerente sentarse en ese otro dominio y hacer hablar a los otros tipos. Esto evita el problema de pasar los tipos a través de ese agujero.
he estado divagando por un tiempo aquí ahora, así que dejaré que sea, pero con esta información que debería ser capaz de entender y hacer uso de los artículos encontrados a través de Google que consultar un poco más fácil.
¿Por qué necesitaría para hacer eso? ¿Por qué no puedes usar Assembly.Load? –
No quiero bloquear el dll que está cargado. Quiero tener la capacidad de cargar dinámicamente, cambiar el código, compilar y volver a cargarlo. –
Luego cambie su pregunta a preguntar eso, y responderé. –