views:

79

answers:

1

Hi all,

I have been using Unity for quite a while but I have always used it with constructor injection. In an effort to reduce the number of classes I have to inject into my view models (as my commands rely on them) I thought I would try creating a concept that uses Property Injection and thus quash the requirement for the large constructor parameter lists. Here is the scenario...

I am creating a View Model that has Commands located on properties that use/update the hosing View Model in some way. I wish to pass the instance of the View Model into the constructors of the Commands located on the View Models properties. E.g.

public MainViewModel
{
    public MainViewModel()
    {
        Customers = new ObservableCollection<CustomerViewModel>();
    }        

    [Depedency("LoadCommand")]
    public ICommand LoadCustomersCommand { get; set; }

    public ObservableCollection<CustomerViewModel> Customers { get; private set; }
}

public LoadCustomersCommand : ICommand
{
    public LoadCustomersCommand(MainViewModel mainViewModel)
    {
        //Store view model for later use
    }

    //... implementation
}

//Setup code in App.Xaml

IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<ICommand, LoadCommand>("LoadCommand");
unityContainer.RegisterType<MainViewModel>(new ContainerControlledLifetimeManager());

When I resolve the MainViewModel class I get a StackOverflow exception (if Visual Studio comes back at all). Now I would expect Unity to create an instance of the MainViewModel first then as it is basically a singleton, then look at the instance of the View Model and create the Command passing in the newly created MainViewModel, but obviously I am wrong.

Any ideas?

+2  A: 

This is Circular References error, and this as it said, this is developer's responsibility to avoid it. So MainViewModel references to LoadCustomersCommand wich is refferences to MainViewModel -> StackOverflow.

So the only you can do is

public class MainViewModel
{
    public MainViewModel()
    {
        Customers = new ObservableCollection<CustomerViewModel>();
    }        

    //no dependency.
    public ICommand LoadCustomersCommand { get; set; }

    public ObservableCollection<CustomerViewModel> Customers { get; private set; }
}

and to resolve you'll need to do the following

var mainModel = unityContainer.Resolve<MainViewModel>();
mainModel.LoadCustomersCommand =     unityContainer.Resolve<ICommand>("LoadCommand");
er-v
Thanks for the answer and your link. I thought that may be the case but due to the property injection I thought the MainViewModel would have been in the container at the time the properties class is instantiated and the 'circular' reference would not be an issue - but obviously not. Thanks for cleaning that up!