我试图使用AppDomains来隔离和运行我的应用程序中的代码。 我需要做的是为每个客户端创建新的AppDomain,在该AppDomain下,我需要创建另一个包含需要隔离的代码的类的实例。我还需要以某种方式存储创建的实例,以便稍后当创建它的同一客户端再次调用时我可以访问它。 我现在创造它的方式是:
private Dictionary<string, IsolatedClass> isolatedClassesList = new Dictionary<string, IsolatedClass>();
public void Initialize(string clientId)
{
AppDomain appDomain = AppDomain.CreateDomain("New AppDomain");
IsolatedClass isolatedClass = (IsolatedClass)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(IsolatedClass).FullName);
isolatedClass.Initialize(clientId);
isolatedClassesList.Add(clientId, isolatedClass);
}
AppDomain的创建和第一次调用“Initiliaze(clientId)
”方法运行正常。将它存储在字典中(供以后使用)也没有任何例外。
当我尝试稍后获取以前创建的IsolatedClass
的实例时会出现问题:
public void DoSomething (string clientId)
{
IsolatedClass isolatedClass = isolatedClassesList.First(x => x.Key == clientId).Value;
isolatedClass.RunIsolatedMethod();
}
抛出null refference异常(它无法检索实例)。当我在那里放置一个断点并检查字典中的内容时,对于Value
,它向我显示:“在此上下文中不支持获取透明代理的运行时类型。”
这是完全错误的做法还是只是一些小错误? 如果我的方法完全错误,还有其他方法可以实现我的目标吗?
修改
显然,IsolatedClass
本身存在一些问题 - 它继承自另一个继承自MarshallByRefObject的类。当我创建简单的虚拟类并使用Kentonbmax的指令开始时,它起作用了。
我将继续测试,看看真正的问题是什么。
答案 0 :(得分:1)
我试过这个,唯一的区别是我的班级在一个不同的库里面。如果您想要与之交互的类类型不同,可以将IsolatedClass替换为MarshalByRefObject作为字典中的值类型。
var domain = AppDomain.CreateDomain(typeof(MyType).Assembly.FullName);
var proxy = domain.CreateInstanceAndUnwrap(
typeof(MyType).Assembly.FullName,
typeof(MyType).FullName) as MyType;
您的IsolatedClass中的UnhandledException和DomainUnload事件是卸载AppDomain时处理IsolatedClass中任何资源的好方法。另外,我建议使用'as'而不是直接强制转换,这样你可以检查强制转换是否失败而不会抛出InvalidCast异常。
使用.First是有问题的,因为您无法保证密钥存在,因此可以返回空引用。如果您在调用Initialize时知道clientId,为什么在调用DoSomething时您不知道它?
if(_isolatedClassesList.ContainsKey(clientId)
{
MyType mine = _isolatedClassesList[clientId] as MyType;
mine.MyMethod();
}