I have a Windows Form. It contains many controllers: Grids, buttons, and even a TreeView. Events are defined on most of them. For example, there are multiple independent events that query or command my SQL server in independent ways. For almost all cases, the Interface Segregation Principle forces me to not merge these interfaces.
Because I'm doing dependency injection, the constructor for my Windows Form is massively over-injected. I have something like four parameters in the form's constructor just for a single grid. Example include: initial population of the grid, querying the list of values for a combobox in one cell of it, repopulating certain types of cell when one other type changes, etc. I reckon that it won't be long before my constructor has something absurd like 20 arguments, all interfaces that query the server.
Is this avoidable in Windows Forms? At a guess, I think I'd be better off if I could somehow build each component and then feed them in to my constructor rather than letting my form know about the dependencies of each component. That is, I think I'd rather replace
MyForm(IQueryGridTimes TimeQueryRepo, ICommandGridTimeCells TimeCommandRepo, IQueryTheWholeGrid GridInitialPopulator, ..., IQueryForTheTreeView TreeViewPopulator)
with
var grid = new WhateverGrid(IQueryGridTimes TimeQueryRepo, ICommandGridTimeCells TimeCommandRepo, IQueryTheWholeGrid GridInitialPopulator)
var tress = new WhateverTreeview(QueryForTheTreeView TreeViewPopulator)
MyForm(grid, ..., trees,)
Is this both wise and possible? I'm open to other approaches and do not need to assume any dependency injection container (I'd rather not use any).
There are many different ways to achieve something similar to what you want.
One quick way to minimize the number of dependencies is to aggregate some of them. Four or more dependencies just to populate one grid seems quite excessive. Instead you could have a repository dependency of some kind that exposes all the necessary data coming from your cache or permanent storage. An interface can hold more than one function.
Alternatively, you can just not use constructors. Most DI frameworks use them out of convention, but that's all it is. You can easily write a DI framework that injects into properties instead, and you then need to only provide properties for your engine to fill.
As a follow up to the previous suggestion, it's relatively trivial to write a source generator handle the creation of DI objects for you, without needing to resort to reflection. Not that reflection is that bad when you have just a few dozen objects in the first place, but source genning them is definitely better.