首页 > 解决方案 > Is it good practice to have ALL dependencies in a base class?

问题描述

I have a WPF application using the MVVM pattern. I'm using Autofac as the DI container. Like other applications similar to mine, I have a ViewModelBase class which implements the INotifyPropertyChanged interface and also resolves dependencies registered in the container:

public class ViewModelBase : ObservableObject
{
    protected IErrorHandler _errorHandler;
    protected IEventAggregator _eventAggregator;
    protected ICustomDialogService _customDialogService;
    protected IUserSettingsRepository _userSettingsRepository;
    protected IReferralRepository _referralRepository;
    protected Notification _notification;
    protected IPrinting _printingService;
    protected ILookupRepository _lookupRepository;
    protected IWorklistRepository _worklistRepository;
    protected IDialogCoordinator _dialogCoordinator;

    public ViewModelBase()
    {
        _errorHandler = AppContainer.Resolve<IErrorHandler>();
        _eventAggregator = AppContainer.Resolve<IEventAggregator>();
        _customDialogService = AppContainer.Resolve<ICustomDialogService>();
        _userSettingsRepository = AppContainer.Resolve<IUserSettingsRepository>();
        _referralRepository = AppContainer.Resolve<IReferralRepository>();
        _notification = AppContainer.Resolve<Notification>();
        _printingService = AppContainer.Resolve<IPrinting>();
        _lookupRepository = AppContainer.Resolve<ILookupRepository>();
        _worklistRepository = AppContainer.Resolve<IWorklistRepository>();
        _dialogCoordinator = AppContainer.Resolve<IDialogCoordinator>();
    }
}

The app has approx 20 view models which all require the use of different dependencies - sometimes it will require none. Is it good practice for every view model to have access to these dependencies even if will never use them?

标签: c#wpfmvvmdependency-injection

解决方案


You usually provide the dependencies via the Class Constructor or similar, not from within the constructor. So in fact none of your classes should know anything of your DI-container. Instead the container resolves the dependencies in the calling context and provides them to the class constructor. It is the callers responsibility to resolve dependencies, not the responsibility of your class. This is the whole point of the Inversion of Control-principle.

Having said this your dependencies should be resolved similar to this:

var errorHandler = AppContainer.Resolve<IErrorHandler>();
var eventAggregator = AppContainer.Resolve<IEventAggregator>();
var myModel = new MyModel(errorHandler, eventAggregator);

This way myModel gets only those dependencies it actually needs for working properly.

To create another model:

var customDialogService = AppContainer.Resolve<ICustomDialogService>();
var userSettingsRepository = AppContainer.Resolve<IUserSettingsRepository>();
var myModel = new MyModel2(customDialogService, userSettingsRepository);

推荐阅读