将代理对象克隆到当前AppDomain

本文关键字:AppDomain 代理 对象 | 更新日期: 2023-09-27 18:09:13

对于我的项目,我需要访问来自其他。net程序集的资源,但我不想让它们保持加载,因为我可能会加载同一程序集的不同版本。

因此,我创建了另一个AppDomain,我使用CreateInstanceAndUnwrap来创建一个自定义类,从MarshalByRefObject下降。在这个类中,我加载程序集,它有一个返回资源对象(字符串,位图等)的函数。

现在的问题是,在临时AppDomain被卸载后(除了像结构这样的值类型对象),我不能保留对这些对象的引用,抛出appdomainunloaddexception。

那么,是否有可能将从另一个AppDomain获得的对象复制到当前的AppDomain,知道这些对象都可能是可序列化的或实现可序列化的?

需要注意的是,Bitmap继承自MarshalByRefObject,实现了isserializable,并且具有Serializable属性。下面是演示这个问题的一小段代码。

class ImageGrabber : MarshalByRefObject 
{
     public Image GetImage() { return new Bitmap(16,16); }
}
//testing
var tmpDomain = AppDomain.CreateDomain("test");
var proxy = (ImageGrabber)tmpDomain.CreateInstanceAndUnwrap(
     typeof(ImageGrabber).Assembly.FullName, 
     typeof(ImageGrabber).FullName);
Bitmap myImage = proxy.GetImage();
AppDomain.Unload(tmpDomain);
pictureBox.Image = myImage;//throws AppDomainUnloadedException 

将代理对象克隆到当前AppDomain

在这种情况下,您可以使用System.Drawing.ImageConverter:

var myImage = proxy.GetImage();
var converter = new ImageConverter();
var data = (byte[])converter.ConvertTo(myImage, typeof(byte[]);
AppDomain.Unload(tmpDomain);
pictureBox.Image = (Bitmap)converter.ConvertFrom(data);

注意:在你的问题的代码,我不认为这编译,顺便说一句:

Bitmap myImage = proxy.GetImage();
HTH

,

看起来位图不喜欢被序列化…它的许多属性的类型都没有标记为可序列化的,甚至Save方法也不起作用,因为它必须使用代理对象无法序列化的属性。因此,我别无选择,只能在临时AppDomain中运行的代码中将图像转换为流(或字节数组也可以工作)。

然后,该流仍然附加到AppDomain,但幸运的是,流类型序列化没有任何障碍,所以我可以将其复制到MemoryStream中。