将代理对象克隆到当前 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 - 如何在场景中访问(或获取渲染/片段代理)克隆的网格?