Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Hollywood Principle + DI + WPF + Unity

I'm currently starting with the development of a new WPF application where I use Unity as a DI container. As of now, I'm doing DI like this in the App.xaml.cs

protected override void OnStartup(StartupEventArgs e)
    {
        var container = new UnityContainer();
        UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        container = (UnityContainer)section.Configure(container);
        WPFUnityContainer.Instance = container;

        var mainwindow = new MainWindow();
        var mainmodel = container.Resolve<ViewModel.MainWindowViewModel>();
        mainwindow.DataContext = mainmodel;
        mainwindow.Show();

        base.OnStartup(e);
    }

The MainWindowViewModel's ctr looks like this:

public MainWindowViewModel(IUserRepository userRepository, IGroupRepository groupRepository)
    {
        this._ManagementWorkSpaces = new ObservableCollection<WorkspaceViewModel>();
        this._ManagementWorkSpaces.Add(new ManageApplicationsViewModel());
        this._ManagementWorkSpaces.Add(new ManageUserViewModel(userRepository, groupRepository));

    }

Now let's have a look at the ManageUserViewModel:

public ManageUserViewModel(IUserRepository userRepository, IGroupRepository groupRepository)

    {...
      this._ManageGroupsCommand = new DelegateCommand(() =>
        {
            LookupGroupDialogViewModel vm=new LookupGroupDialogViewModel(groupRepository);
            View.LookupGroupDialogWindow vw=new View.LookupGroupDialogWindow();
            ModalDialogService.Service.ShowDialog(vw, vm, returnedVM =>
                {
                    if (returnedVM.SelectedGroup!=null)
                        this.SelectedUser.Groups.Add(returnedVM.SelectedGroup);
                });
        });

     }

As you can see I'm injecting the groupRepository only to pass it on to the LookUpGroupDialogViewModel. I could leave the IGroupRepository out of the ManageUserViewModel's ctr and resolve it directly through the container but I think that violates the hollywood principle. How can I, in WPF, resolve all my dependencies so that the container calls me ? :)

like image 740
hoetz Avatar asked Aug 31 '11 08:08

hoetz


1 Answers

It looks to me as if the View Models you are adding to the _ManagementWorkSpaces must have some sort of common abstraction (unless the collection is completely untyped and simply accepts any object) - I'm assuming that this is the WorkspaceViewModel type.

This means that you can neatly solve your problem by changing the constructor to look like this:

public MainWindowViewModel(ObservableCollection<WorkspaceViewModel> workSpaces)
{
    this._ManagementWorkSpaces = workSpaces;
}

Let your Composition Root worry about how the ObservableCollection<WorkspaceViewModel> instance is resolved.

like image 200
Mark Seemann Avatar answered Sep 20 '22 21:09

Mark Seemann