城堡温莎代理产生内存泄漏

Castle windsor proxy generate memory leak

Castle windsor 在 MVC 应用程序中使用,如下所述: Plugging Windsor in MVC

在我的应用程序中有一个区别,那就是方法 AddControllerLoggingFunctionality:

var controller = ((IController)container.Kernel.Resolve(controllerType)).AddControllerLoggingFunctionality();

这个方法在记录器中 class:

[DebuggerStepThrough]
public static class Logger
{
    private static readonly Castle.DynamicProxy.ProxyGenerator proxyGenerator;
    static Logger()
    {
        proxyGenerator = new Castle.DynamicProxy.ProxyGenerator();
        Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(
            typeof(ServiceContractAttribute));
    }

    public static TInterface AddControllerLoggingFunctionality<TInterface>(this TInterface implementation)
        where TInterface : class
    {
        if (implementation == null)
        {
            throw new ArgumentNullException("implementation");
        }

        if (!typeof(TInterface).IsInterface)
        {
            throw new Exception("Type of 'TInterface' must be interface.");
        }

        Castle.DynamicProxy.ProxyGenerationOptions options =
            new Castle.DynamicProxy.ProxyGenerationOptions();

        var origAttribs = implementation.GetType().GetCustomAttributesData();
        if (origAttribs != null)
        {
            foreach (var origAttrib in origAttribs)
            {
                options.AdditionalAttributes.Add(
                    AttributeUtil.CreateBuilder(origAttrib));
            }
        }

        return (TInterface)proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(
            implementation,
            options,
            new ControllerLoggingInterceptor(implementation.GetType()));
    }
}

还有 有人可以解释一下吗?为什么 IController 可以调用 AddControllerLoggingFunctionality 它有什么作用?

由于此更改,此控制器永远不会从内存中释放(当 container.Kernel.ReleaseComponent(控制器);被称为),我得到内存泄漏。 "Object tracked by release policy" 计数器一直在增加。 如果我删除 AddControllerLoggingFunctionality,那么每次调用 ReleaseComponent 时 "Object tracked by release policy" 计数器都会减少并且不会发生内存泄漏。

您没有在控制器上调用 Release(),而是在您手动创建的代理上调用它,因此 Release() 只是对 Windsor 的禁止操作,因为它不知道对象,因此一直跟踪控制器组件。

如果您使用 Windsor 的 built-in interception support,则不必担心这个问题,因为 Windsor 在通过其内部管理的代理时知道如何处理组件。

如果您想在更改为 Windsor 的内置支持之前对此进行测试,请将您的代理投射到 Castle.DynamicProxy.IProxyTargetAccessor 并调用 DynProxyGetTarget() 以获取您需要传递给 Release().

(此答案是从我们在 Castle Users 邮件列表中的 discussion 复制的)