Inject EventAggregator into ViewModel with Caliburn Micro
Asked Answered
U

2

0

Extracted from the Caliburn Micro documentation on EventAggregator:

// Creating the EventAggregator as a singleton.
public class Bootstrapper : BootstrapperBase {
    private readonly SimpleContainer _container =
        new SimpleContainer();

     // ... Other Bootstrapper Config

    protected override void Configure(){
        _container.Singleton<IEventAggregator, EventAggregator>();
    }

    // ... Other Bootstrapper Config
}

// Acquiring the EventAggregator in a viewModel.
public class FooViewModel {
    private readonly IEventAggregator _eventAggregator;

    public FooViewModel(IEventAggregator eventAggregator) {
        _eventAggregator = eventAggregator;
    }
}

So the question is how do you get the instance of EA created by Bootstrapper to inject into your VM?

var svm = new SomeViewModel(?);

I tried using Caliburn.Micro.IoC.Get method but that didn't work...

Unconscious answered 28/6, 2013 at 19:29 Comment(0)
K
7

No, you don't var svm = new SomeViewModel(?) and don't use IoC.Get because service location is becoming an anti-pattern.
The pattern suggested by the article author is best-practice, that is you should inject your dependencies to the objects that need them through constructor injection.
I don't know how to say it in any other way, but Make Your Application Composable and create an Architecture for you Presentation Layer.
I would check the Screens, Conductors and Composition article because it has some great ideas related to what i am saying and the application that accompanies it is a great one.
I would also read about dependency injection.

Kepi answered 28/6, 2013 at 21:27 Comment(2)
That was just an example, once you add IEventAggregator eventAggregator to ViewModel constructor and you no longer have the default constructor you must pass an instance of EA when you instantiate your VM... my question was how to get the instance to pass it into VM constructor...Unconscious
@DeanKuga That's is my point, you don't create an view models manually, you let CaliburnMicro create the entire object graph for you from the bootstrapper and if you have a ViewModel where you received eventAggregator through the constructor, keep a reference to it through a read only instance variable and use this instance in your ViewModel if that ViewModel needs to manually create other ViewModels that take IEventAggregator in their constructor.Kepi
C
1

I wrote the article you are referencing. Sniffer is correct (please leave the green tick with him). Caliburn.Micro invests heavily in a concept called composition. What this means is that the whole object graph is constructed implicitly at run time, or composed, if you will.

The idea is that your "shell" ViewModel is created by the bootstrapper, the shell in turn creates other ViewModels and so on down the graph. This allows constructor injection to be used and provides the best composability.

However, there are times when this is not the desired functionality, for this we do provide a service locator by way of the IoC class; As Sniffer stated though, most use cases for service location are deemed to be anti patterns and as such it's usage should be severely scrutinized otherwise it will bite you on the ass down the road.

I am putting the finishing touches on two new articles for both IoC and our built in dependency container, SimpleContainer, once these are up I will add the relevant links to the EventAggregator docs which should provide more context around injection sites and best practice.

Centerboard answered 3/7, 2013 at 10:26 Comment(2)
Did you have those links? Very interest in "proper" way to add UserControls to a View that require Dependency Injection. New to Caliburn.Micro.Monohydroxy
Both are live now under EventAggregator and SimpleContainer respectively caliburnmicro.codeplex.com/documentationCenterboard

© 2022 - 2024 — McMap. All rights reserved.