跨越应用程序域边界访问对象

[ 1056 查看 / 3 回复 ]

一个应用程序域中的代码可以和另一个应用程序域中的类型和对象相互通信。但是,这样的通信必须通过一种预先定义的机制进行。大多数类型在跨越应用程序域边界时是通过传值的方式(by value)来进行封装和传送处理(marshal)的。换句话说,如果我们在一个应用程序域中构造了一个对象,然后又将该对象的引用传递给了另一个应用程序域,那么CLR必须首先将该对象的字段序列化到一个内存块中,然后再将该内存块传递给另一个应用程序域,最后再执行反序列化得到新的对象。
1

评分次数

    TOP

    目的应用程序域将使用这个新创建的对象引用,它不会访问原来应用程序域中的对象。对于以传值方式进行远程传送(remote)的对象来说,对象的类型必须应用有System.Serializable的Attribute。
    TOP

    除了应用System.Serializable的Attribute的类型外,继承自System.MarshalByRefObject的类型也可以为对象提供跨越应用程序域边界的访问能力。但是,这样的访问是通过传引用(by Reference)而非传值(by value)来进行的。假设我们在一个应用程序域中创建了一个对象(其类型继承自System.MarshalByRefObject)。当该对象的引用被传递给一个目的应用程序域时,CLR实际上会在目的应用程序域中创建一个代理类型的实例,目的应用程序域中的代码将使用这个代理对象引用。原来的对象及其字段仍然驻留在原来的应用程序域中。代理对象实际上是一个封装器(wrapper),它知道怎样调用原来应用程序域中的对象上的实例方法。同样,目的应用程序域不会直接访问原来应用程序域中的对象。
    TOP

    线程和应用程序域之间不存在一对一的关系。当一个应用程序域中的线程调用另一个应用程序域中的方法时,线程会在两个应用程序域间跳转。这意味着跨越应用程序域边界的方法调用会被同步地执行。但是,在任何一个给定的时刻,一个线程都被认为只存在于一个应用程序域中。我们可以调用System.Threading.Thread的静态方法GetDomail来获得当前执行线程所在的应用程序域(由一个System.AppDomain对象所标识)。

    当一个应用程序域被卸载时,CLR会知道哪些线程位于该应用程序域中,并在这些线程中强制产生一个ThreadAbortException异常,使它们退出该应用程序域。一旦这些线程离开该应用程序域,CLR会使所有指向要卸载的应用程序域中的对象的那些代理对象变得无效。在这之后,所有对无效代理对象的调用都导致一个System.AppDomainUnloadedException异常被抛出,引用原来的对象已经不存在了。
    TOP