Трябваше да правя това няколко пъти и проучих много различни решения.
Решението, което намирам за най-елегантно и лесно за изпълнение, може да се приложи като такова.
1. Създайте проект, който можете да създадете прост интерфейс
интерфейсът ще съдържа подписи на всички членове, които искате да се обадите.
public interface IExampleProxy
{
string HelloWorld( string name );
}
Важно е да поддържате този проект чист и олекотен. Това е проект, към който и двата AppDomain
могат да се позовават и ще ни позволи да не препращаме към Assembly
, който искаме да заредим в отделен домейн от нашия клиентски модул.
2. Сега създайте проект, който има кода, който искате да заредите в отделен AppDomain
.
Този проект, както и при клиентския проект, ще препраща към прокси проекта и вие ще внедрите интерфейса.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. След това в клиентския проект заредете код в друг AppDomain
.
И така, сега създаваме нов AppDomain
. Може да посочи основното местоположение за препратки към сглобяване. Пробването ще провери за зависими сборки в GAC и в текущата директория и AppDomain
базовия 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 );
ако трябва, има много различни начини за зареждане на сборка. Можете да използвате различен начин с това решение. Ако имате квалифицирано име на асемблиране, тогава обичам да използвам CreateInstanceAndUnwrap
, тъй като то зарежда байтовете на асемблиране и след това инстанцира вашия тип вместо вас и връща object
, което можете просто да прехвърлите към вашия прокси тип или, ако не го направите, в строго типизиран код можете да използвате времето за изпълнение на динамичен език и да присвоите върнатия обект на променлива с тип dynamic
, след което просто да извикате членове на това директно.
Ето го.
Това позволява да заредите сборка, към която вашият клиентски проект няма препратка в отделен AppDomain
и да извикате членове в нея от клиента.
За да тествам, обичам да използвам прозореца Modules във Visual Studio. Той ще ви покаже вашия домейн на клиентски модул и какви всички модули са заредени в този домейн, както и вашия нов домейн на приложение и какви сборки или модули са заредени в този домейн.
Ключът е да се уверите, че кодът или извлича MarshalByRefObject
, или може да бъде сериализиран.
`MarshalByRefObject ще ви позволи да конфигурирате живота на домейна, в който се намира. Например, кажете, че искате домейнът да бъде унищожен, ако проксито не е било извикано в рамките на 20 минути.
Надявам се това да помогне.
person
SimperT
schedule
09.04.2018