we're quite new to DI and we're refactoring our application to use Prism/Unity. We're almost there but got stuck on a circular dependency. I've been reading a lot, there are a lot of similar questions but I'm in doubt as to what would be a 'correct' solution in our situation.
The application is similar to some IDEs. We have a project explorer, search, documents, ... The documents are actually treeviews with nodes of INodeViewModel. Note that the code samples are minimized versions of the real code.
We have a IDockingService
that manages the tool and document items.
public interface IDockingService
{
INodeViewModelNavigationService NodeViewModelNavigationService { get; }
ExplorerViewModel ExplorerViewModel { get; }
SearchViewModel SearchViewModel { get; }
ReadOnlyCollection<ToolItemViewModel> ToolItemViewModels { get; }
ReadOnlyCollection<DocumentItemViewModel> DocumentItemViewModels { get; }
}
And we have a ISpecificationViewModelService
that manages all the INodeViewModels and has the connection with the model.
public interface ISpecificationViewModelService
{
INodeViewModel RootX { get; }
INodeViewModel RootY { get; }
INodeViewModel RootZ { get; }
}
We have two requirements that conflict.
- When a new node is created somewhere we want to navigate to it. Currently we pass
IDockingService
via constructor injection to the concreteSpecificationViewModelService
implementation and further down to each NodeViewModel. - Certain tools in the
DockingService
need to know about theISpecificationViewModelService
. For example the Explorer needs to display all the roots.
Since DockingItemService
creates and manages the toolitems such as the Explorer it needs the ISpecificationViewModelService
. But the ISpecificationViewModelService
needs the IDockingService
to be able to navigate to a node. Circular troubles.
Our first attempt didn't have this issue because we let the the tool items be created in the composition root but that didn't seem correct. Instances we not managed together nicely.
From reading around I understand that a factory (or another third class) could help out here. I'm not seeing how yet. I think I understand that the problem is that DockingService
only needs SpecificationViewModelService
to create the toolitems and vice versa. A factory could take this circular trouble away but I'm not sure it is a correct solution. The container can only be used in the composition root but wouldn't a facory (which needs the container?) then just be hiding the container and take over its work under a different name?
What would be a correct way to handle this problem?