Мені довелося це робити кілька разів і досліджував багато різних рішень.
Рішення, яке я вважаю найелегантнішим і легким у виконанні, можна реалізувати як таке.
1. Створіть проект, за допомогою якого можна створити простий інтерфейс
інтерфейс буде містити підписи будь-яких учасників, яких ви хочете зателефонувати.
public interface IExampleProxy
{
string HelloWorld( string name );
}
Важливо підтримувати проект чистим та грамотним. Це проект, на який обидва AppDomain
можуть посилатися і дозволить нам не посилатися на те, що Assembly
ми хочемо завантажити в окремий домен з нашої клієнтської збірки.
2. Тепер створіть проект, який містить код, який ви хочете завантажити окремо AppDomain
.
Цей проект, як і клієнтський proj, посилається на proxy proj, і ви реалізуєте інтерфейс.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. Далі, в проекті клієнта, завантажте код в інший AppDomain
.
Отже, зараз ми створюємо нове AppDomain
. Можна вказати базове місце для посилань на збірку. Зондування перевірить наявність залежних збірок у GAC та в поточному каталозі та AppDomain
базовій локації.
// 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 );
якщо вам потрібно, існує безліч різних способів завантаження збірки. Ви можете використовувати інший спосіб з цим рішенням. Якщо у вас є ім'я, яке має збірку, я хотів би використовувати, CreateInstanceAndUnwrap
оскільки він завантажує байти збірки, а потім інстанціює ваш тип для вас і повертає object
те, що ви можете просто передати на ваш тип проксі-сервера або, якщо ви не це, в сильно набраний код, ви могли б використовуйте динамічний час виконання мови та призначте повернений об’єкт dynamic
введеній змінній, а потім просто зателефонуйте членам на цю адресу безпосередньо.
Там у вас є.
Це дозволяє завантажити збірку, на яку ваш клієнтський proj не посилається окремо, AppDomain
та зателефонувати членам на нього від клієнта.
Для тестування мені подобається використовувати вікно Модулі у Visual Studio. Він покаже вам домен вашої клієнтської збірки та те, які всі модулі завантажуються в цей домен, а також ваш новий домен додатка та які склади чи модулі завантажуються в цей домен.
Ключовим моментом є або переконайтесь, що код або є результатом, MarshalByRefObject
або є його послідовними.
`MarshalByRefObject дозволить вам налаштувати термін служби його домену. Наприклад, скажіть, що ви хочете, щоб домен знищився, якщо проксі-сервер не викликав за 20 хвилин.
Я сподіваюся, що це допомагає.