Eu tive que fazer isso várias vezes e pesquisei muitas soluções diferentes.
A solução que acho mais elegante e fácil de realizar pode ser implementada como tal.
1. Crie um projeto em que você pode criar uma interface simples
a interface conterá assinaturas de todos os membros que você deseja chamar.
public interface IExampleProxy
{
string HelloWorld( string name );
}
É importante manter este projeto limpo e leve. É um projeto que ambos AppDomain
podem fazer referência e nos permitirá não fazer referência ao domínio Assembly
que desejamos carregar em seprate de nosso assembly cliente.
2. Agora crie um projeto que tenha o código que deseja carregar separadamente AppDomain
.
Este projeto, assim como o proj cliente, fará referência ao proj proxy e você implementará a interface.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. Em seguida, no projeto do cliente, carregue o código em outro AppDomain
.
Então, agora criamos um novo AppDomain
. Pode especificar o local de base para referências de montagem. A investigação verificará os assemblies dependentes no GAC e no diretório atual e no AppDomain
loc de base.
// 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 );
se for necessário, existem várias maneiras diferentes de carregar uma montagem. Você pode usar uma maneira diferente com esta solução. Se você tiver o nome qualificado do assembly, eu gosto de usar o, CreateInstanceAndUnwrap
pois ele carrega os bytes do assembly e, em seguida, instancia o seu tipo para você e retorna um object
que você pode converter para o seu tipo de proxy ou, se não, para um código fortemente tipado, pode use o tempo de execução de linguagem dinâmica e atribua o objeto retornado a uma dynamic
variável digitada e, em seguida, chame os membros diretamente.
Aí está.
Isso permite carregar uma montagem que o projeto do seu cliente não tenha referência em uma AppDomain
e chamar membros do cliente.
Para testar, gosto de usar a janela Módulos no Visual Studio. Ele mostrará seu domínio de assembly do cliente e quais módulos são carregados nesse domínio, bem como seu novo domínio de aplicativo e quais assemblies ou módulos são carregados nesse domínio.
A chave é certificar-se de que o código deriva MarshalByRefObject
ou é serializável.
`MarshalByRefObject permitirá que você configure o tempo de vida do domínio em que está. Por exemplo, digamos que você deseja que o domínio seja destruído se o proxy não for chamado em 20 minutos.
Eu espero que isso ajude.