【问题标题】:Marshalling Assembly from another AppDomain从另一个 AppDomain 编组程序集
【发布时间】:2011-10-14 18:57:24
【问题描述】:

是否可以在不将该程序集加载到当前应用程序域的情况下从另一个应用程序域保存对程序集的引用?

我正在修复动态生成程序集并运行动态生成代码的 Windows 服务中的内存泄漏。问题是生成的程序集被加载到当前应用程序域中并且永远无法卸载。

其中一个 Windows 服务库中的方法具有以下签名:

public Assembly CreateMethod(ObservableCollection<Field> sourceFields, Field destinationField)

此方法为程序集创建代码并使用 CSScript 库 LoadMethod 函数加载它:

result = CSScript.LoadMethod(scriptFunction.ToString());

稍后,来自 CreateMethod 的这个 Assembly 引用用于在生成的程序集中运行一个函数。

public object Run(Field destinationField, ObservableCollection<LinkField> sourceLinkFields, DataRow mainRow, Assembly script) {

   ...

   var method = script.GetStaticMethodWithArgs("*.a" + Id.ToString().Replace("-", String.Empty), argumentTypes.ToArray());

   return method(arguments.ToArray());
}

我想知道是否可以将动态生成的程序集加载到另一个应用程序域中,并通过某种类型的代理运行它们,而无需将其加载到当前应用程序域中。

编辑:

我想知道当程序集加载到另一个 AppDomain 中时,我是否可以在一个 AppDomain 中使用 Assembly 类引用。查看 MSDN 文档,他们展示了如何使用 MarshalByRefObject。基本上我试图避免将签名更改为我的 CreateMethod 函数,但是如果这不可能,我可能需要更改它以返回 MarshalByRefObject。

更新:

我最终把对 CSScript.LoadMethod 的调用放在另一个应用程序域中,在那里我保存了一个 Dictionary 我然后让 CreateMethod 返回一个 Guid 而不是一个程序集,然后我传递这个 Guid 直到运行调用。 Run 调用现在将 Guid 作为参数而不是 Assembly。在 Run 调用中,我将 Guid 传递给另一个应用程序域,运行方法,并通过继承 MarshalByRefObject 的类返回结果对象。

【问题讨论】:

标签: c# .net c#-4.0 appdomain .net-assembly


【解决方案1】:

如果您不希望在主 AppDomain 中使用动态程序集,则必须将 CreateMethod 移动到另一个 AppDomain,因为一旦您拥有 Assembly 的实例,它就会被加载。换句话说,不可能在另一个应用程序域中保存对程序集的引用,而只能跨应用程序域调用该程序集。

在不更改签名和一堆代码的情况下,您似乎需要移动最小数量:1)程序集创建和 2)Run。然后有Run的执行结果。

至于CreateMethod,我认为您希望另一个程序集中的方法“包装”CreateMethod 并返回某种可以传递给Run 的令牌。这几乎就像以某种方式更改签名......

【讨论】:

  • 谢谢,这是我最终采用的方法。我不得不更改 CreateMethod 和 Run 方法签名,但仍然能够保持代码的原始设计。
【解决方案2】:

这是AppDomain 的主要功能之一!去看看文档吧

【讨论】:

  • 感谢您的链接,我已经用一些额外的细节更新了这个问题。我仍然不清楚是否需要将 CreateMethod 的签名更改为 MarshalByRefObject 或者是否可以将返回类型保持为 Assembly
  • 为了将来帮助他人,我想知道:您之前是否看过AppDomain的文档?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 2010-09-12
相关资源
最近更新 更多