Inject EventAggregator into ViewModel with Calibur

2019-02-20 15:35发布

问题:

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...

回答1:

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.



回答2:

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.