C# 如何跨AppDomains发送XElement对象
我有一个从不同的dll文件加载外部程序集的应用程序。我正在将程序集加载到以前创建的另一个域。所有程序集都返回XElement对象,我需要将此对象用于主AppDomain中的其他方法,但XElement对象没有可序列化属性,这就是为什么我无法按原样发送此对象。从外部库中获取XElement对象非常重要。我尝试使用序列化来实现此目的,但每次都失败了 我尝试创建一些包装类。这个类只是从XElement创建流,我试图在主域中读取这个流,但这个流当时是关闭的 如果有人能帮我解决这个问题,我会非常高兴的。 提前谢谢C# 如何跨AppDomains发送XElement对象,c#,appdomain,C#,Appdomain,我有一个从不同的dll文件加载外部程序集的应用程序。我正在将程序集加载到以前创建的另一个域。所有程序集都返回XElement对象,我需要将此对象用于主AppDomain中的其他方法,但XElement对象没有可序列化属性,这就是为什么我无法按原样发送此对象。从外部库中获取XElement对象非常重要。我尝试使用序列化来实现此目的,但每次都失败了 我尝试创建一些包装类。这个类只是从XElement创建流,我试图在主域中读取这个流,但这个流当时是关闭的 如果有人能帮我解决这个问题,我会非常高兴的。
private XElement CallModule(string modulePath, string moduleName,
Dictionary<string, string> parameters)
{
AppDomainSetup moduleDomainSetup = new AppDomainSetup();
moduleDomainSetup.ApplicationBase = AppDomain.CurrentDomain.RelativeSearchPath;
AppDomain moduleDomain =
AppDomain.CreateDomain("moduleDomain", null, moduleDomainSetup);
try
{
Module remoteobj = (Module)moduleDomain.CreateInstanceFromAndUnwrap(
HttpContext.Current.Request.MapPath(modulePath),
moduleName + "." + moduleName);
Module.WrappedStream remoteResult =
remoteobj.Execute(queryString["command"], parameters);
XElement res = XElement.Load(remoteResult.Stream);
return res;
}
catch (Exception ex)
{
throw ex;
}
finally
{
AppDomain.Unload(moduleDomain);
}
}
private XElement调用模块(字符串modulePath、字符串moduleName、,
字典参数)
{
AppDomainSetup moduleDomainSetup=新建AppDomainSetup();
moduleDomainSetup.ApplicationBase=AppDomain.CurrentDomain.RelativeSearchPath;
AppDomain moduleDomain=
CreateDomain(“moduleDomain”,null,moduleDomain设置);
尝试
{
模块remoteobj=(模块)moduleDomain.CreateInstanceFromAndUnwrap(
HttpContext.Current.Request.MapPath(modulePath),
moduleName+““+”moduleName);
Module.WrappedStream remoteResult=
remoteobj.Execute(queryString[“command”],参数);
XElement res=XElement.Load(remoteResult.Stream);
返回res;
}
捕获(例外情况除外)
{
掷骰子;
}
最后
{
卸载(moduleDomain);
}
}
您可以使用将其保存到TextWriter或流您可以使用将其保存到TextWriter或流您不能使用XElement跨AppDomain边界。潜在原因-XElement可以表示必须跨AppDomain边界封送的巨大对象树/大量数据
虽然您可以让代码正常工作(即通过保存到流并重新加载),但这可能不是最好的主意。您将丢失元素(即父元素)的上下文,并且可能会无意中序列化/反序列化大量数据。考虑重构,这样就可以在创建新的AppDe域中处理XBasic的数据,而不是将自定义对象(RealAlgZeLabor或RealMalHAL)返回到主AppDeave.
注:
- 我假设您的示例代码只是示例,创建/删除AppDomain以调用单个方法并不是地球上最快的事情。如果是一次性操作,可能完全可以,但如果它以任何非平凡的频率重复,请确保检查性能是否符合您的目标
- 如果只需要
(再次假设实际代码的作用大于最后
),则不需要抛出
/捕获
)抛出
- 我假设您的示例代码只是示例,创建/删除AppDomain以调用单个方法并不是地球上最快的事情。如果是一次性操作,可能完全可以,但如果它以任何非平凡的频率重复,请确保检查性能是否符合您的目标
- 如果只需要
(再次假设实际代码的作用大于最后
),则不需要抛出
/捕获
)抛出
您还可以用命令模式尝试一下吗?我发现很奇怪,XElement向IXmlSerializable接口确认-(公共类XElement:XContainer,IXmlSerializable)您是否测试了仅返回字符串或int,这对您有效。@orn,XElement不可二进制序列化,也不能通过引用封送,这是跨appdomain.Yaroslav使用它所必需的,因为您的示例缺少在其他appdomain中运行并创建流的代码部分。因此,无法诊断特定调用失败的原因。(我不认为这是个好主意-似乎是我的答案)。我发现很奇怪,XElement确认了IXmlSerializable接口-(公共类XElement:XContainer,IXmlSerializable)您是否测试了仅返回字符串或int,这对您有效。@orn,XElement不可二进制序列化,也不能通过引用封送,这是跨appdomain.Yaroslav使用它所必需的,因为您的示例缺少在其他appdomain中运行并创建流的代码部分。因此,无法诊断特定调用失败的原因。(我不认为这是个好主意——似乎是我的答案)。我很乐意拒绝使用应用程序域,但当我尝试在主域中加载dll库时,此dll文件将被锁定,并且在进程不会被终止之前,我无法删除/替换此库。这也是一个重要的问题,因为我应该能够在运行时将旧库替换为新库。我很乐意拒绝使用应用程序域,但当我尝试在主域中加载dll库时,此dll文件将被锁定,并且我无法删除/重新加载
Module remoteobj = (Module)moduleDomain.CreateInstanceFromAndUnwrap(
HttpContext.Current.Request.MapPath(modulePath),
moduleName + "." + moduleName);
Module.WrappedStream remoteResult =
remoteobj.Execute(queryString["command"], parameters);
XElement res = XElement.Load(remoteResult.Stream);
return res;