J'ai dû faire cela plusieurs fois et j'ai recherché de nombreuses solutions différentes.
La solution que je trouve la plus élégante et la plus facile à réaliser peut être mise en œuvre telle quelle.
1. Créez un projet que vous pouvez créer une interface simple
l'interface contiendra les signatures de tous les membres que vous souhaitez appeler.
public interface IExampleProxy
{
string HelloWorld( string name );
}
Il est important de garder ce projet propre et léger. C'est un projet que les deux AppDomain
peuvent référencer et qui nous permettra de ne pas référencer le que Assembly
nous souhaitons charger dans un domaine séparé de notre assembly client.
2. Créez maintenant un projet contenant le code que vous souhaitez charger séparément AppDomain
.
Ce projet comme avec le projet client référencera le proj proxy et vous implémenterez l'interface.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. Ensuite, dans le projet client, chargez le code dans un autre AppDomain
.
Alors, maintenant, nous créons un nouveau AppDomain
. Peut spécifier l'emplacement de base des références d'assemblage. Le sondage vérifiera les assemblys dépendants dans GAC et dans le répertoire actuel et la AppDomain
localisation 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 );
si vous en avez besoin, il existe une multitude de façons différentes de charger un assemblage. Vous pouvez utiliser une méthode différente avec cette solution. Si vous avez le nom qualifié d'assembly, j'aime utiliser le CreateInstanceAndUnwrap
car il charge les octets de l'assembly, puis instancie votre type pour vous et retourne un object
que vous pouvez simplement convertir en votre type de proxy ou si vous ne le faites pas en code fortement typé, vous pouvez utilisez le runtime de langage dynamique et affectez l'objet retourné à une dynamic
variable typée, puis appelez simplement les membres directement dessus.
Voilà.
Cela permet de charger un assembly auquel votre projet client n'a pas de référence dans un fichier séparé AppDomain
et d'appeler les membres dessus à partir du client.
Pour tester, j'aime utiliser la fenêtre Modules dans Visual Studio. Il vous montrera votre domaine d'assembly client et quels modules sont chargés dans ce domaine, ainsi que votre nouveau domaine d'application et quels assemblys ou modules sont chargés dans ce domaine.
La clé est de s'assurer que le code dérive MarshalByRefObject
ou est sérialisable.
`MarshalByRefObject vous permettra de configurer la durée de vie du domaine dans lequel il se trouve. Exemple, disons que vous voulez que le domaine soit détruit si le proxy n'a pas été appelé dans 20 minutes.
J'espère que ça aide.