将代理对象克隆到当前 AppDomain

Posted

技术标签:

【中文标题】将代理对象克隆到当前 AppDomain【英文标题】:Clone proxy object into current AppDomain 【发布时间】:2016-09-28 20:08:22 【问题描述】:

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

为此,我创建了另一个 AppDomain,我使用 CreateInstanceAndUnwrap 创建了一个继承自 MarshalByRefObject 的自定义类。在那个类中,我加载了程序集,它具有返回资源对象(字符串、位图等)的功能。

现在的问题是,在临时 AppDomain 被卸载后,我无法保留对这些对象的引用(除了像结构这样的值类型对象),会引发 AppDomainUnloadedException。

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

需要注意的是,Bitmap 继承自 MarshalByRefObject,实现 ISerializable 并具有 Serializable 属性。这是一个小sn-p来演示这个问题。

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 

【问题讨论】:

【参考方案1】:

在这个特定的上下文中,你可以使用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,

【讨论】:

【参考方案2】:

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

然后,该流仍然附加到 AppDomain,但幸运的是流类型可以顺利序列化,因此我可以将其复制到 MemoryStream 中。

【讨论】:

以上是关于将代理对象克隆到当前 AppDomain的主要内容,如果未能解决你的问题,请参考以下文章

Forge Viewer - 如何在场景中访问(或获取渲染/片段代理)克隆的网格?

Java 对象克隆

对象的克隆(clone)技术:像变量值传递一样创建新对象

是否可以在不手动将重写的克隆方法添加到 C++ 中的每个派生类的情况下克隆多态对象?

自己动手搭建nginx服务集群反向代理

如何将JavaFx与Jade框架链接到代理