3

我有一个使用 Autofac 和 MVP 模式的非常简单的 WinForms POC。在这个 POC 中,我通过 Autofac 的 Resolve 方法从父表单打开一个子表单。我遇到的问题是子表单如何保持打开状态。在Display()子窗体的方法中,如果我调用ShowDialog()子窗体保持打开状态,直到我关闭它。如果我调用Show(),子窗体会闪烁并立即关闭 - 这显然不好。

我已经为将 Autofac 集成到 WinForms 应用程序进行了大量搜索,但是我没有找到任何关于 Autofac/WinForms 集成的好的示例。

我的问题是:

  1. 用我的方法显示非模态子表单的正确方法是什么?
  2. 有没有比我的方法更好的方法在 WinForms 应用程序中使用 Autofac?
  3. 如何确定没有内存泄漏以及 Autofac 是否正确清理子窗体的模型/视图/演示者对象?

下面仅显示相关代码。

谢谢,

凯尔

public class MainPresenter : IMainPresenter
{
    ILifetimeScope container = null;
    IView view = null;

    public MainPresenter(ILifetimeScope container, IMainView view)
    {
        this.container = container;
        this.view = view;
        view.AddChild += new EventHandler(view_AddChild);
    }

    void view_AddChild(object sender, EventArgs e)
    {
        //Is this the correct way to display a form with Autofac?
        using(ILifetimeScope scope = container.BeginLifetimeScope())
        {
            scope.Resolve<ChildPresenter>().DisplayView(); //Display the child form
        }
    }

    #region Implementation of IPresenter

    public IView View
    {
        get { return view; }
    }

    public void DisplayView()
    {
        view.Display();
    }

    #endregion

}

public class ChildPresenter : IPresenter
{
    IView view = null;

    public ChildPresenter(IView view)
    {
        this.view = view;
    }

    #region Implementation of IPresenter

    public IView View
    {
        get { return view; }
    }

    public void DisplayView()
    {
        view.Display();
    }

    #endregion

}


public partial class ChildView : Form, IView
{
    public ChildView()
    {
        InitializeComponent();
    }

    #region Implementation of IView

    public void Display()
    {
        Show(); //<== BUG: Child form will only flash then instantly close.
        ShowDialog(); //Child form will display correctly, but since this call is modal, the parent form can't be accessed
    }

    #endregion

}
4

1 回答 1

2

看看这段代码:

using(ILifetimeScope scope = container.BeginLifetimeScope())
{
    scope.Resolve<ChildPresenter>().DisplayView(); //Display the child form
}

首先,您最好使用子生命周期范围。如果您从顶级容器中解析,则对象将与该容器一样长(通常是应用程序的整个生命周期)。

但是,这里有一个问题。DisplayView调用时Form.Show,它立即返回。using块结束,子作用域被释放,它的所有对象(包括视图)也被释放。

在这种情况下,您不需要using声明。您要做的是将子生命周期范围绑定到视图,以便在关闭视图时释放子范围。请参阅我FormFactory其他答案之一中的示例。还有其他方法可以使这个想法适应您的架构 - 例如,您可以在注册(ContainerBuilder)中进行。

于 2013-04-11T03:23:18.777 回答