11

I have a WPF app which, when it starts, looks at the file system for some config files

For each config file it finds, it displays some info in a different window

Each window has an associated ViewModel object which is bound to the windows datacontext

So a new ViewModel is created for each config file. An object representing the data in the config file is passed into the viewmodels constructor

However, the View model also has other dependancies passed into the constructor

The code looks something like this (in a bootstrapper initiated from app.xaml)

foreach (WindowConfig config in ConfigManager.GetConfigs())
{
    IMyService svc = new MyService();

    //change to resolve from IoC container
    MyViewModel vm = new MyViewModel(config, svc);

    Window1 view = new Window1();

    view.DataContext = vm;

    window.show();
}

I want to use Castle IoC contaoiner resolve these dependancies. I know how to do that for IMyService, but how can I do it for the specific class that has been created from the config file ?

thanks

ChrisCa
  • 10,876
  • 22
  • 81
  • 118

2 Answers2

8

Always remember that in the application code, pulling from the container is never the solution. Application code should be unaware that there's a DI container in play.

The general solution when you need to resolve a dependency based on a run-time value is to use an Abstract Factory.

In your case, the factory might look like this (assuming that your config variables are strings:

public interface IViewModelFactory
{
    IViewModel Create(string configuration);
}

Now you can inject the IViewModelFactory as a single dependency into the class that loops through the configuration files.

To implement IViewModelFactory you can either do it by hand or use Castle Windsor's Typed Factory Facility to implement it for you.

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • hmmm...not quite getting this. isn't this just adding a layer of abstraction to the problem? I still need to pass a parameter to the create method but also need to resolve one out of the container. Any chance you could explain a bit more ... would my factory look like this : public interface IViewModelFactory { IViewModel Create(WindowConfig configuration, IMyService svc); – ChrisCa Mar 23 '11 at 08:55
  • Also, this is all taking place in my bootstrapping class. Which is where I am first hitting the container. So to passing a dependancy into that will mean it's not resolved by the container...as you can probably tell, I am a little confused – ChrisCa Mar 23 '11 at 09:05
  • 3
    I see you have answer this question a few times before - this is the explanation that finally made me understand...thanks http://stackoverflow.com/questions/1926826/cant-combine-factory-di – ChrisCa Mar 23 '11 at 09:51
2

You can pass parameters to Windsor, that it should use when resolving the constructor, by using the overload of IWindsorContainer.Resolve that takes an IDictionary as a parameter. In this dictionary, the key should be the parameter name, and the value should be the object to use as the parameter value:

var arguments = new Dictionary<string,object> {{ "config", config }, { "service", svc } };
var viewModel = container.Resolve<MyViewModel>(arguments);
driis
  • 161,458
  • 45
  • 265
  • 341
  • Is it possible to resolve the concrete type for IMyService from the container (i.e. specified in the Windsor XML or Fluent Interface). And just have the config parameter passed in the dictionary? Maybe I need to change this so config is passed in via parameter injection rather than constructor injection? (Though I would prefer not tpo do that) – ChrisCa Mar 22 '11 at 21:56