How to use DI at the birth of new Windows Forms downstream?

I have a Unity DI container that works first with my Windows Forms application. In Program.cs , I have the following:

 static void Main() { var container = BuildUnityContainer(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(container.Resolve<MainForm>()); } private static IUnityContainer BuildUnityContainer() { var container = new UnityContainer(); container.RegisterType<ITest, MyTestClass>(); container.RegisterType<ISomeOtherTest, MyOtherClass>(); return container; } 

In my MainForm constructor, I have the following that works :

 private readonly ITest test; public MainForm(ITest test) { this.test = test; InitializeComponent(); } 

The container is enabled and the code is working fine. Problem / question: how can I create a new form from MainForm , say Form2 , which has the following constructor:

 private readonly ISomeOtherTest someOtherTest; public Form2(ISomeOtherTest someOtherTest) { this.someOtherTest = someOtherTest; InitializeComponent(); } 

If I try the following in MainForm :

 Form2 form2 = new Form2(); form2.Show(); 

It will break, complaining that I did not pass the meaning to the constructor. However, I already allowed my container, and I thought that all subsequent containers would be allowed. Obviously, I missed something, although this does not work.

Does this mean that I should before loading all the dependencies in MainForm , even if this form does not use it, so I can pass them to any new instances of the form that I create? It would be strange if I had 50 dependencies to allow and that the constructor for the top-level form would take them all. Please help to understand my understanding, since I used Unity and DI containers almost exclusively in web APIs and MVCs, which already have a DI resolver built-in for controllers, so I have to miss some parts and understand here.

+4
source share
1 answer

You have to create your form like this

 Form2 form = container.Resolve<Form2>(); 

You did not use a container, so the form does not have a constructor that takes no arguments. If you allow it with a container, it will examine the constructor, find the dependencies, and automatically add them to the constructor for you.

So, maybe your problem is that you do not have access to the container in your MainForm? If this is a problem, there are two approaches.

Insert an IUnityContainer into the MainForm constructor

However ... people who live by the "compound root" pattern will tell you that you should only use the container from the root of your application (in this case, probably Main ()). Another option is ...

Create a Form2 factory class from your composition root (Main), which is introduced in MainForm, and MainForm uses the factory to create Form2

You should read more in the Root Theory of Thinking ...

Composition root


Update

I have never had to do this before, but I think the second method will look something like this ...

 public class Form2Factory : IForm2Factory { private readonly ISomeOtherTest someOtherTest; public Form2Factory(ISomeOtherTest someOtherTest) { this.someOtherTest = someOtherTest; } public Form2 Create() { return new Form2(someOtherTest); } } public class MainForm { private readonly IForm2Factory form2Factory; public MainForm(IForm2Factory form2Factory) { this.form2Factory = form2Factory; } private void DoingSomething() { Form2 form = form2Factory.Create(); form.Show(); } } 
+6
source

Source: https://habr.com/ru/post/1489366/


All Articles