In my AdministrationController I use a PupilViewModel like:
_adminRepo.GetSchoolclassPupilList().ForEach(s =>
{
SchoolclassViewModel sVM = new SchoolclassViewModel(s, _adminRepo);
foreach (PupilViewModel pVM in sVM.PupilListViewModel)
{
pVM.Documents.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);
pVM.Documents.AddDocumentDelegate += new Action(OnAddDocument);
pVM.Documents.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);
}
SchoolclassList.Add(sVM);
});
The PupilViewModel is created that way:
public SchoolclassViewModel(Schoolclass schoolclass, IAdministrationRepository adminRepo)
{
_schoolclass = schoolclass;
_adminRepo = adminRepo;
PupilListViewModel = new ObservableCollection<PupilViewModel>();
schoolclass.Pupils.ForEach(p => PupilListViewModel.Add(new PupilViewModel(p, _adminRepo)));
}
As you surely noticed the PupilViewModel takes 2 paramter in its Constructor. The important one is the 2nd paramter which is a service/repository to be specific its the IAdministrationRepository instance.
There exists now another Controller called IncidentReportingController. In its Constructor I do the same as in the AdministrationController:
// When I now try to wrap my pupils into a ViewModel I have a problem:
IEnumerable<Pupil> pupils = incidentRepo.GetPupilIncidentReportDocumentList();
PupilViewModels = new ObservableCollection<PupilViewModel>(pupils.Select(p => new PupilViewModel(p, ???)));
A.) Either I do not want to pass a Service to the PupilViewModel because there is no reason to update a property i the PupilViewModel as it is readonly in the View.
B.) In my AdministrationController
I get data from the service from this Aggregation
:
1 Schoolclass
has N Pupils
and 1 Pupil
has N Documents
. Those entities are wrapped into
SchoolclassViewmodels
, PupilViewModels
and DocumentViewModels
...
Now in my IncidentController
I get data from the service too and my Aggregation
is pretty similar:
1 Pupil
has N IncidentReports
and 1 IncidentReport
has N Documents
. Those entities are wrapped into
PupilViewModels
, IncidentReportViewModels
, DocumentViewModels
...
PROBLEM is => In the PupilViewModel class it wraps already a DocumentListViewModel. Now I need the PupilViewModel again to wrap a IncidentReportListViewModel and Later again I have 1 Pupil has 1 SeatingChair and wrap those again. That means I have to pass THREE Services to the PupilViewModel although I do not always need them.
Its hard for me to cut right to the chase with the problem but somehow I feel that is not the right way.
So How do I re-use the same ViewModel which wrap entities with different aggregations having different services?
Without knowing how far down the path you are...I would highly suggest you take a look at Prism which makes use of Unity. As stated on Unitys web site...
What you gain when making use of these varying frameworks is the extensive decoupling and the 'duty' of instantiation among other things. You then no longer need to worry about the parameters being passed into the constructor as the framework will resolve them for you.
You can also for instance set the lifetime of a registered type, say IDoSomethingController, to an actually type, DoSomethingController...and set it's lifetime to behave as a Singleton should you need the single instance being passed around as someone requests an object of type IDoSomethingController.
Once you make use of these frameworks you are no longer 'newing' up an instance, you are making use of the framework to provide the reuse that you are looking for.
EDIT: Since you stated you are using MEFedMVVM; the DI framework exists. Your PupilViewModel is an instance of an ObservableCollection. This is overkill, pass this through. a ViewModel should need to carry additionally weight before you depart simply passing the data through. Your ViewModels seem to be trying to represent objects verusu concepts. What I mean is that you could simply have a SchoolViewModel which exposes pupils, classes, etc.. Those items become Models which can be aggregated in some form on your ViewModel. The ViewModel is meant to be the mediator to the View. It can contain a wealth of information across varying models and services, becoming a single point of data for the View.
You seem to have un-necessary use of a repository on your view model? I would expect to see a repository on your business types, not your view model.
For example...
The pupils view model would simply require a school instance, injected by Unity (or your chosen IOC), all of the methods to save, update etc are stored away in the business object.
or even Static methods on the business object which accept a school type in their constructors? Either way, I would expect your view mode to be calling methods on the Business Objects, it seems more logical for the School object to know the details of how it is saved (including an validation that might need to be done before eventually allowing the save to the database).
On the business object, that is where you would have an instance of the School Repository, the business object doesnt need to know the mechanics of how it is pursisted, thats handed off the repository to worry about, the business object would simply perform any validation of business rules to itself and then make the decision of wether it should save itself to the database or not by calling methods on the repository.
Example:
The repository would handle any code that is needed to save the record to the database.
The School Entity should have no knowledge of HOW to save itself, there is no reason why it cant know the details of what it needs in order to save itself though... the ViewModel does not need to know that level of detail (and shouldnt), using dependency injection, the business object (School) simply knows that it needs an ISchoolRepository, instantiates it and then calls the methods on it.
This would solve your problem...
Does that make sense? Hopefully you can see the seperation of concerns which is what you have started to try and acheive... hope it helps!
Ben
I will answer my own question and those who followd my question or answered here please test/check my solution and comment wether its a worth a solution:
The origion problem was I reuse the PupilViewModel at 3 places in different context. One time the PVM`s ctor needs a AdministrationService the other usage it needs a IncidentReportingService and the last time the 3rd service I forgot...
Now injecting ALL 3 services at ALL 3 places seems dumb to me:
Doing this 3 times looks like bad architecture. Actually I need this: Just wrap the pupil and inject all 3 services WHEN I NEED them really!!!
http://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/
Scroll down guys and you see MEFedMVVM can do Ctor and Prop injection!!! Totally overlooked that option and its the MEF default injection (Property Injection).
EDIT: That does not work, because of this:
You see how the _adminRepo is passed to the new created PupilViewModel? At that time when the Ctor is run the Property AdministrationRepository is still null to get the Repo from there... bad :/