在我的默认(完全信任)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...'类型的权限失败。”
(关于 AppDomainStarter 的定义,见我对另一个问题的回答。)
请注意,ApplicationBase
C:\Temp不是包含包含域的程序集的文件夹。这是故意的;我的目标是在新的 AppDomain 中加载第二个第 3 方不受信任的程序集,第二个程序集位于 C:\Temp (或其他任何地方,甚至可能是网络共享)。但在我可以加载第二个程序集之前,我需要Domain
在新的 AppDomain 中加载我的类。这样做会成功,但由于某种原因,我无法跨 AppDomain 边界订阅事件(我可以调用方法,但不能订阅事件)。
更新:显然,当订阅沙盒 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() { }
}
但是,我仍然无法订阅该活动。新错误是“无法加载文件或程序集 'TestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 或其依赖项之一。系统找不到指定的文件。”
在某种程度上,这是有道理的,因为我将“错误”文件夹“C:\Temp”指定为我的新 AppDomain 的 ApplicationBase,但在某种程度上这没有任何意义,因为“TestApp”程序集已经加载到两个 AppDomain 中. 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
必须是包含不受信任程序集的文件夹,而不是包含我的程序集的文件夹。