Autofac & WinForms Integration Issue
I have a very simple WinForms POC utilizing Autofac and the MVP pattern. In this POC, I am opening a child form from the parent form via Autofac's Resolve method. What I'm having issues with is how the child form stays open. In the Display()
method of the child form, if I call ShowDialog()
the child form remains open until I close it. If I call Show()
, the child form flashes and instantly closes - which is obviously not good.
I've done numerous searches for integrating Autofac into a WinForms application, however I've not found any good examples on Autofac/WinForms integration.
My questions are:
Only relevant code is shown below.
Thanks,
Kyle
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
}
Look at this code:
using(ILifetimeScope scope = container.BeginLifetimeScope())
{
scope.Resolve<ChildPresenter>().DisplayView(); //Display the child form
}
First, it is good that you used a child lifetime scope. If you resolve out of the top-level container, the objects will live as long as that container (which is usually the whole lifetime of the application).
However, there is a problem here. When DisplayView
calls Form.Show
, it returns immediately. The using
block ends, the child scope is disposed, and all of its objects (including the view) are also disposed.
In this case, you do not want a using
statement. What you want to do is tie the child lifetime scope to the view so that when the view is closed, the child scope is disposed. See the FormFactory
in one of my other answers for an example. There are other ways you could adapt this idea to your architecture - you could do it in the registration (ContainerBuilder) for example.
下一篇: Autofac和WinForms集成问题