C# 如何跨AppDomains发送XElement对象

C# 如何跨AppDomains发送XElement对象,c#,appdomain,C#,Appdomain,我有一个从不同的dll文件加载外部程序集的应用程序。我正在将程序集加载到以前创建的另一个域。所有程序集都返回XElement对象,我需要将此对象用于主AppDomain中的其他方法,但XElement对象没有可序列化属性,这就是为什么我无法按原样发送此对象。从外部库中获取XElement对象非常重要。我尝试使用序列化来实现此目的,但每次都失败了 我尝试创建一些包装类。这个类只是从XElement创建流,我试图在主域中读取这个流,但这个流当时是关闭的 如果有人能帮我解决这个问题,我会非常高兴的。

我有一个从不同的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。潜在原因-XElement可以表示必须跨AppDomain边界封送的巨大对象树/大量数据

虽然您可以让代码正常工作(即通过保存到流并重新加载),但这可能不是最好的主意。您将丢失元素(即父元素)的上下文,并且可能会无意中序列化/反序列化大量数据。考虑重构,这样就可以在创建新的AppDe域中处理XBasic的数据,而不是将自定义对象(RealAlgZeLabor或RealMalHAL)返回到主AppDeave.

注:

  • 我假设您的示例代码只是示例,创建/删除AppDomain以调用单个方法并不是地球上最快的事情。如果是一次性操作,可能完全可以,但如果它以任何非平凡的频率重复,请确保检查性能是否符合您的目标
  • 如果只需要
    最后
    (再次假设实际代码的作用大于
    抛出
    ),则不需要
    捕获
    /
    抛出
与其尝试序列化XElement,不如序列化modulePath、moduleName和参数,然后使用modulePath、moduleName和参数重新创建XElement对象

您还可以尝试使用命令模式吗

与其尝试序列化XElement,不如序列化modulePath、moduleName和参数,然后使用modulePath、moduleName和参数重新创建XElement对象


您还可以用命令模式尝试一下吗?

我发现很奇怪,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;