В моей по умолчанию (полный доверия) AppDomain Я хочу, чтобы создать песочницу AppDomain и подписаться на событие в нем:Почему я не могу подписаться на событие в частичном доверенности AppDomain?
class Domain : MarshalByRefObject
{
public event Action TestEvent;
}
Domain domain = AppDomainStarter.Start<Domain>(@"C:\Temp", "Domain", null, true);
domain.TestEvent +=() => { }; // SecurityException
Подписка завершается с сообщением «Запрос на разрешение типа«System.Security. Permissions.ReflectionPermission, mscorlib, Version = 4.0.0.0 ... "failed."
(Для определения AppDomainStarter см my answer to another question.)
Обратите внимание, что ApplicationBase
C: \ Temp является НЕ папку, которая содержит сборку, которая содержит домен. Это преднамеренно; моя цель - загрузить вторую стороннюю ненадежную сборку внутри нового AppDomain, и эта вторая сборка находится в C: \ Temp (или где-нибудь еще, может быть, даже сетевой ресурс). Но прежде чем я смогу загрузить вторую сборку, мне нужно загрузить мой класс Domain
внутри нового AppDomain. Это удается, но по какой-то причине я не могу подписаться на событие через границу приложения (я могу вызывать методы, но не подписаться на события).
UPDATE: Очевидно, что при подписке на событие в песочнице AppDomain как метод абонента, так и класс, содержащий подписчика, должны быть общедоступными. Например:
public static class Program
{
class Domain : MarshalByRefObject
{
public event Action TestEvent;
public Domain() { Console.WriteLine("Domain created OK"); }
}
static void Main()
{
string loc = @"C:\Temp";
Domain domain = AppDomainStarter.Start<Domain>(loc, "Domain", null, true);
// DIFFERENT EXCEPTION THIS TIME!
domain.TestEvent += new Action(domain_TestEvent);
}
public static void domain_TestEvent() { }
}
Однако STILL не может подписаться на мероприятие. Новая ошибка: «Не удалось загрузить файл или сборку TestApp, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null» или одну из его зависимостей. Система не может найти указанный файл ».
В некотором смысле это имеет смысл, потому что я указал «неправильную» папку «C: \ Temp» как ApplicationBase моего нового AppDomain, но в некотором смысле это не имеет никакого смысла, потому что сборка «TestApp» равна уже загружен в оба AppDomains. Как возможно, что CLR не может найти сборку, которая уже загружена?
Кроме того, нет никакой разницы, если добавить разрешение на доступ к папке, которая содержит мою сборку:
string folderOfT = Path.GetFullPath(Path.Combine(typeof(T).Assembly.Location, ".."));
permSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, folderOfT));
// Same exception still occurs
я могу «исправить» эту проблему, используя различные значения для AppDomainSetup.ApplicationBase
:
string loc = Path.GetFullPath(Assembly.GetExecutingAssembly().Location + @"\..");
Это исключает исключение, но я не могу использовать это «решение», потому что целью AppDomain является загрузка ненадежной сборки из другой папки, кроме папки, содержащей мою собственную сборку. Поэтому loc
должен быть папкой, в которой содержится ненадежная сборка, а не та, которая содержит мою сборку.
(i) Я не пытаюсь сделать какое-либо отражение, (ii) ReflectionPermission предоставляет доступ для доступа к частным членам любого доступного типа; AFAIK НЕ требуется для доступа к открытым членам. Я не хочу предоставлять ReflectionPermission, потому что он может открыть дыры в безопасности. – Qwertie
(i), как вы видели, это не обязательно ваш код, но инфраструктура, которая должна это сделать (вот почему создание публичного типа решило эту проблему). Ii) достаточно справедливо, и вы все равно обходите эту проблему. –
Можете ли вы не сделать в папку «plug in» находится подпапка существующей базы приложений? то вам не нужно изменять приложение вашего домена приложения, и сборка будет загружена правильно. Вы всегда можете ограничить файл ввода-вывода в каталоге подключений через FileIOPermission –