He tenido que hacer esto varias veces y he investigado muchas soluciones diferentes.
La solución que encuentro más elegante y fácil de lograr se puede implementar como tal.
1. Crea un proyecto que puedas crear con una interfaz simple
la interfaz contendrá las firmas de los miembros a los que desee llamar.
public interface IExampleProxy
{
string HelloWorld( string name );
}
Es importante mantener este proyecto limpio y ligero. Es un proyecto al que ambos AppDomain
pueden hacer referencia y nos permitirá no hacer referencia al Assembly
que deseamos cargar en un dominio separado de nuestro ensamblaje de cliente.
2. Ahora cree un proyecto que tenga el código que desea cargar por separado AppDomain
.
Este proyecto, al igual que el proyecto de cliente, hará referencia al proyecto de proxy y usted implementará la interfaz.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. A continuación, en el proyecto del cliente, cargue el código en otro AppDomain
.
Entonces, ahora creamos un nuevo AppDomain
. Puede especificar la ubicación base para referencias de ensamblaje. El sondeo buscará ensamblados dependientes en GAC y en el directorio actual y la AppDomain
base loc.
// set up domain and create
AppDomainSetup domaininfo = new AppDomainSetup
{
ApplicationBase = System.Environment.CurrentDirectory
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain exampleDomain = AppDomain.CreateDomain("Example", adevidence, domaininfo);
// assembly ant data names
var assemblyName = "<AssemblyName>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null|<keyIfSigned>";
var exampleTypeName = "Example";
// Optional - get a reflection only assembly type reference
var @type = Assembly.ReflectionOnlyLoad( assemblyName ).GetType( exampleTypeName );
// create a instance of the `Example` and assign to proxy type variable
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( assemblyName, exampleTypeName );
// Optional - if you got a type ref
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( @type.Assembly.Name, @type.Name );
// call any members you wish
var stringFromOtherAd = proxy.HelloWorld( "Tommy" );
// unload the `AppDomain`
AppDomain.Unload( exampleDomain );
si es necesario, hay un montón de formas diferentes de cargar un ensamblaje. Puede utilizar esta solución de una forma diferente. Si tiene el nombre calificado de ensamblado, entonces me gusta usar el, CreateInstanceAndUnwrap
ya que carga los bytes de ensamblaje y luego crea una instancia de su tipo para usted y devuelve un object
que puede convertir simplemente a su tipo de proxy o, si no, en un código fuertemente tipado, podría use el tiempo de ejecución del lenguaje dinámico y asigne el objeto devuelto a una dynamic
variable escrita y luego simplemente llame a los miembros directamente.
Ahí tienes.
Esto permite cargar un ensamblado al que el proyecto de su cliente no tiene referencia en un AppDomain
y llamar a los miembros desde el cliente.
Para probar, me gusta usar la ventana Módulos en Visual Studio. Le mostrará el dominio de ensamblado de su cliente y todos los módulos que se cargan en ese dominio, así como su nuevo dominio de aplicación y qué ensamblajes o módulos se cargan en ese dominio.
La clave es asegurarse de codificar o derivar MarshalByRefObject
o serializable.
`MarshalByRefObject le permitirá configurar la vida útil del dominio en el que se encuentra. Por ejemplo, digamos que desea que el dominio se destruya si no se ha llamado al proxy en 20 minutos.
Espero que esto ayude.