来自另一个AppDomain的编组程序集
本文关键字:程序集 AppDomain 另一个 | 更新日期: 2023-09-27 18:11:21
是否有可能从另一个应用域中保存对程序集的引用,而不将该程序集加载到当前应用域中?
我正在修复一个动态生成程序集并运行动态生成的代码的Windows服务中的内存泄漏。问题是生成的程序集被加载到当前应用程序域中,并且永远不能卸载。
在一个Windows服务库中有一个方法具有以下签名:
public Assembly CreateMethod(ObservableCollection<Field> sourceFields, Field destinationField)
此方法为程序集创建代码,并使用CSScript库LoadMethod函数加载它:
result = CSScript.LoadMethod(scriptFunction.ToString());
之后,这个来自CreateMethod的程序集引用将用于在生成的程序集中运行函数。
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在另一个应用程序域,我保持一个字典,然后我让CreateMethod返回一个Guid而不是一个程序集,然后我传递这个Guid,直到运行调用。Run调用现在接受Guid作为参数,而不是程序集。在Run调用中,我将Guid传递给另一个应用域,运行该方法,并通过继承MarshalByRefObject的类返回结果对象。
如果你不想要动态程序集在主AppDomain中,你必须将CreateMethod
移动到另一个AppDomain,因为一旦你有了Assembly
的实例,它就被加载了。换句话说,不可能在另一个应用程序域中保存对程序集的引用,而只能跨应用程序域调用该程序集。
在不改变签名和一堆代码的情况下,您似乎需要移动最小数量:1)程序集创建和2)Run
。然后有Run
的实现对结果进行编组。
就CreateMethod
而言,我认为您需要在另一个程序集中使用一个方法来"包装"CreateMethod
并返回某种可以传递给Run
的令牌。这几乎就像在某种程度上改变签名…
这是AppDomain的主要功能之一!看一下文档