MVC3 IControllerFactory ReleaseController内存泄漏

时间:2012-03-15 14:34:31

标签: c# asp.net-mvc-3 design-patterns dependency-injection

在我们的项目中,我们使用MefControllerFactory,这些是我们在global.asax中设置为application_start的代码ControllerBuilder.Current.SetControllerFactory(new Project.Helper.MefControllerFactory(container));

问题是当我们在结果中运行.NET Profiler时,即使我们在“ReleaseController”方法中配置控制器也会出现内存泄漏问题。原始消息是“实例已处理但仍可从一个或多个根处访问。由于通常不再使用已处置的实例,这可能表示内存泄漏。调查实例以查明实例是否是无意的保持活力,或者如果问题可以忽略。“ 有没有解决这个问题的方法?

第二条消息是: “具有直接EventHandler根的已处置实例 已处置的实例直接由EventHandler生成,即该实例仅用作EventHandler的目标,并且不通过委托就无法从任何其他根目录访问它。由于不再使用已处置的实例,并且EventHandler是内存泄漏的常见原因,因此该问题是内存泄漏的强烈迹象。“

public class MefControllerFactory : IControllerFactory
{
    private CompositionContainer _container;
    private DefaultControllerFactory defaultControllerFactory;

    public MefControllerFactory(CompositionContainer container)
    {
        _container = container;
        this.defaultControllerFactory = new DefaultControllerFactory();
    }

    #region IControllerFactory Members

    public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        IController controller = null;

        controller = _container.GetExportedValueOrDefault<IController>(controllerName);

        if (controller == null)
            return this.defaultControllerFactory.CreateController(requestContext, controllerName);

        return controller;
    }

    public void ReleaseController(IController controller)
    {
        IDisposable disposable = controller as IDisposable;
        if (disposable != null)
            disposable.Dispose();
    }

    #endregion


    public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        return System.Web.SessionState.SessionStateBehavior.Default;
    }
}

...谢谢

1 个答案:

答案 0 :(得分:5)

这是我为my book的代码示例创建的基于MEF的控制器工厂:

public class MefControllerFactory : DefaultControllerFactory
{
    private readonly CompositionContainer container;
    private readonly Dictionary<IController, Lazy<object, object>> exports;
    private readonly object syncRoot;

    public MefControllerFactory(CompositionContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        this.container = container;
        this.exports = new Dictionary<IController, Lazy<object, object>>();
        this.syncRoot = new object();
    }

    protected override IController GetControllerInstance(
        RequestContext requestContext, Type controllerType)
    {
        var export = this.container.GetExports(
            controllerType, null, null).Single();
        var controller = (IController)export.Value;
        lock (this.syncRoot)
        {
            this.exports.Add(controller, export);
        }
        return controller;
    }

    public override void ReleaseController(IController controller)
    {
        lock (this.syncRoot)
        {
            var export = this.exports[controller];
            this.exports.Remove(controller);

            this.container.ReleaseExport(export);
        }
        base.ReleaseController(controller);
    }
}

在MEF中,您只能通过发布导出而不是导出的来释放对象图。