I'm pretty new to DI and i have a few questions i hoped people could clear up for me, I'm currently working on a WPF-MVVM system that uses Caliburn Micro, using a MEF container.
This application is used to keep track of shipments and has several parts. I hope i can explain this clearly enough, but please do point out if it is't clear.
I have several entities returned from the database (via webservices) examples are shipments
, containers
, packages
.
for each of these entities i have a model which wraps the webservice entity, and a manager, the manager is responsible for the standard CRUD operations via webservices, as well as storing the ObservableCollection
of the model, these managers are then injected into the constructors of viewmodels
that require access to these lists.
So, i have shipment > shipmentManager > shipmentListViewModel, this was done to allow multiple viewmodels
work with the same list of shipments
However, I've started to run into issues where some viewmodels
have constructors with 6+ managers included, and some cases that are only used to pass onto newly constructed dialog viewmodels
.
I'm hoping that someone could suggest a clean solution to this issue, I'm thinking of a single class which will become a container for all managers, and then i can simply inject that container class and use that to get the desired Manager, however I've seen people advising against that method, without clearly stating why.
Also, one other question, my Models implement IEditableObject
and because my managers are responsible for maintaining the list of models, as well as saving changes to those models, would publishing an event inside EndEdit
that the manager picks up be an issue?
EDIT: Code as requested:
The bootstrapper create and exports the required classes:
protected override void Configure()
{
container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
CompositionBatch batch = new CompositionBatch();
IEventAggregator eventAggregator = new EventAggregator();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(eventAggregator);
batch.AddExportedValue<IManager<ShipmentContainer>>(new ContainerManager());
batch.AddExportedValue<IManager<Item>>(new ItemManager());
batch.AddExportedValue<IManager<OrderedItem>>(new OrderedItemManager());
batch.AddExportedValue<IManager<Package>>(new PackageManager());
batch.AddExportedValue<IManager<Proforma>>(new ProformaManager(eventAggregator));
batch.AddExportedValue<IManager<Project>>(new ProjectManager());
batch.AddExportedValue<IManager<Shipment>>(new ShipmentManager(eventAggregator));
batch.AddExportedValue<IManager<PackingItem>>(new PackingListManager(eventAggregator));
batch.AddExportedValue(container);
container.Compose(batch);
}
ContentViewModel handled the menu clicks, which allows for the opening of several diaglogs, the constructor contains a large number of DI:
public LBLContentViewModel(IWindowManager windowManager, IManager<Project> pManager, IEventAggregator eventManager, IManager<Item> iManager, IManager<PackingItem> plManager, IManager<Shipment> sManager)
{
...
}
and dialogs are shows as follows:
public void OpenProject()
{
ProjectSearchViewModel viewModel = new ProjectSearchViewModel(_eventAggregator, _projectManager);
this._windowManager.ShowDialog(viewModel);
}
Hopefully this is the code you wanted to see charleh, if not please let me know and i'll try and provide what is needed.