出于旧版 ASP 代码和新 ASP.NET 代码之间的兼容性原因,我们有一堆 .NET COM 对象,它们将我们的一些 .NET 实用程序暴露给 ASP。在某些情况下,我们需要在 .NET COM 包装器中使用另一个 COM 对象。为了实现高灵活性并避免 PIA 依赖性,我们决定使用动态代码来处理这些 COM 对象。
简化的 C# COM 对象:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace TestCom
{
[ComVisible(true)]
[Guid("6DC92920-8C3C-4C81-A615-BD0E3A332024")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ITestComObject
{
[DispId(1)]
string MyMethod(dynamic dictionary);
}
[ComVisible(true)]
[Guid("F52A463E-F03B-4703-860C-E86CDD6D04E3")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("TestCom.TestComObject")]
public class TestComObject : ITestComObject
{
string ITestComObject.MyMethod(dynamic dictionary)
{
StringBuilder sb = new StringBuilder();
if (dictionary != null)
{
foreach (object key in dictionary)
{
object p = dictionary[key];
if (p != null)
{
sb.AppendFormat("{0}={1}{2}", key, p, Environment.NewLine);
}
}
}
return sb.ToString();
}
}
}
测试 ASP 页面:
<%@ Language=VBScript %>
<%
Dim testObj, params
Set testObj = Server.CreateObject("TestCom.TestComObject")
Set params = Server.CreateObject("Scripting.Dictionary")
params("lang") = "en-US"
params("num") = 42
Response.Write testObj.MyMethod(params)
Set testObj = Nothing
Set params = Nothing
%>
在正常情况下,动态代码将只编译一次,随后的调用将重用它。然而,在我们的例子中,动态代码似乎是在每次调用时编译的。当我将内存分析器附加到 IIS 进程时,我可以清楚地看到来自 Microsoft.CSharp.RuntimeBinder.Semantics 命名空间的其他对象出现在 gen2 中。这有效地导致了我们的 IIS 进程中的内存泄漏。
任何想法如何解决这个动态代码编译问题?请注意,在我们的案例中,重写所有代码以使用 PIA 和 COM 接口并不总是一种选择。