存储在AppDomain下创建的对象实例

时间:2015-10-07 19:24:44

标签: c# reflection

我试图使用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的指令开始时,它起作用了。 我将继续测试,看看真正的问题是什么。

1 个答案:

答案 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();
}