One of possible approaches involves a controller factory. The factory is responsible for creating controllers and views and wiring both together.
The factory should be configurable so you could have different implementations for differnt set of views - a set of views that is used to build an actual ui has its own factory, another test set has another factory etc. All factories are accessed through the same api so that you only reconfigure the factory when necessary. One of the possible ways to implement such factory would be to use an IoC container, it could simplify the implementation but it is not necessary. With the IoC container you would just register different implementations of your views and could reuse the same implementation of the factory whereas without the IoC container you would need an extra implementation of the factory for each set of views.
Then your parent controller creates an instance of the child controller using the factory. The factory returns the child controller with the proper view injected into it. The parent controller calls the ShowView
on the child controller which just makes the view visible or the child controller could even show the view automatically upon creation.
Edit: the example factory that creates controllers/views:
In the controller layer:
public interface IControllerFactory
{
TController CreateControllerAndView<TController>()
where TController : Controller;
}
public class ControllerFactory
{
// actual provider
private static IControllerFactory _provider;
// factory method
public static TController
CreateControllerAndView<TController>() where T : Controller
{
return _provider.CreateController<TController>();
}
public static void SetProvider( IControllerFactory provider )
{
_provider = provider;
}
}
Anytime you want to create a new controller, you refer to the factory:
var controller = ControllerFactory.CreateControllerAndView<UserController>();
Note that the factory doesn't depend on anything, it is merely defined, not yet implemented.
Then, somewhere in the most upper layer, in the startup project probably, you implement a concrete provider:
public class ConcreteControllerFactory : IControllerFactory
{
public TController CreateControllerAndView<TController>()
{
// since you are in the top most layer, you know all types from
// underlaying layers, including controllers and views
// IoC would help here a lot! But without it:
if ( typeof<TController> == typeof<UserController> )
{
IUserView view = new UIUserView();
UserController c = new UserController( view );
}
...
}
}
and then somewhere
ControllerFactory.SetProvider( new ConcreteControllerFactory() );
This way you can plug any specific provider to the factory, the test provider, the ui provider, whatever. The actual implementation could vary but you should get the idea.