I am using autofac to resolve Views and ViewModels in a WPF application. IComponentContext is being passed into the View automatically.
An example:
public BusinessAuto(int proposedCoverageId, IComponentContext componentContext)
{
DataContext = componentContext.Resolve<BusinessAutoViewModel>(new TypedParameter(typeof(Int32), proposedCoverageId));
InitializeComponent();
}
In the XAML for this view there are UserControls being created that have their own ViewModels. An example:
<userControl:AdditionalCoveragesControl Margin="0,10"/>
Autofac is not creating the UserControl (the View is) so Autofac cannot inject dependencies into the UserControl's constructor.
How can I get the reference to IComponentContext into a UserControl that is declared in the initial View's XAML?
I feel that I either need Autofac to somehow create my UserControl, that I need to revert to the discouraged Global static container (ick), or I have to use a DependencyProperty to pass the container down (also ick).
You should not pass componentContext to BusinessAuto view, instead you should pass AdditionalCoveragesControl.
XAML:
Then all your views will be independent from Autofac, you should just register all of them in container.
I wouldn't inject (what is effectively) your container, as this is an inferior form of inversion of control called Service Locator, with deficiencies that can be summed up by your current situation: you end up needing to inject the container into EVERYTHING.
Instead, you need to approach the problem from the point of view of "What is this component in charge of creating, and what does it need to do it?"
As mentioned by Lonni-Loki, one option is to inject a fully formed control but I disagree on that point: if the main view has the responsibility of creating this sub component, then it should create it - but to facilitate that responsibility, you should inject the main view with the services/models/etc it would then need to pass along or otherwise use to create it. Autofac's factory method stubs are ideal for this:
For example if the sub view needs an IFooViewModel, you can inject the container with a Func<IFooViewModel< (a factory method registered with the context), which it can then use to "feed on demand" the new contained view.
(or a Func<arg1, arg2, etc, IFooViewModel>, as your needs require)
One handy rule of thumb is when considering class X, first take anywhere you "new up" anything and instead pass that into the constructor. Now look at the code and ask yourself "If I wanted an instance of class X, what would I need to pass the constructor?" Those are your dependencies.
Let's take a more hands-on example...say you've got a structure like this:
Application creates MainWindow
MainWindow creates SubView1, needs IMainWindowViewModel
SubView1 needs ISubView1Model, IFooService
SubView1 creates SubView2
SubView2 needs ISubView2Model, IBarService
So our ctors would look like:
When setting up your container, you'd have something like so:
(note, I use a variety of IoC containers, so my Autofac syntax might be rusty)
The glorious (and in my opinion, only) use for IoC containers is the "You figure out how to get all the bits based on what I've already told you" part - otherwise, you might as well use manual injection, where you pass in dependencies by hand. That said, our potentially complicated construction of MainWindow is now just:
I hope I didn't make too many typos/errors in the code, but I haven't used Autofac for a while.