What does this mean in Prism/Unity: Container.Resolve<ShellPresenter>()

Edward Tanguay picture Edward Tanguay · Mar 11, 2009 · Viewed 15k times · Source

(from the StockTraderRIBootstrapper.cs file in the Prism V2 StockTrader example app)

What is the difference between this:

ShellPresenter presenter = new ShellPresenter();

and this:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • I understand the second example is treating the container like a factory, walking up to it saying "I need an instantiated object of type ShellPresenter".
  • But what if, e.g. I need to send parameters, what would be the equivalent of "new ShellPresenter(1, true)" etc.?
  • And since the Container has to be told about the ShellPresenter, I expected to find somewhere in the project a place where the ShellPresenter class being registered with the container, e.g. I was expecting

something like this:

Container.RegisterType<IShellPresenter, ShellPresenter>();

but found it nowhere. So how does the container get to know about these types so it can .Resolve them? I rebuilt this in its own project and get a "Resolution of the dependency failed" error, where do I need to register this dependency then?

Any direction/discussion here would be helpful.

Unexplained Answer:

So, in the bootstrapper, when I register the Shell itself:

protected override void ConfigureContainer()
{
    Container.RegisterType<IShellView, Shell>();
    base.ConfigureContainer();
}

then the Container can resolve the ShellPresenter type. So how is the ShellPresenter type registered when I register the Shell type?

The Surprising Answer:

Ok, so it turns out that you don't have to register the type you are trying to resolve but you do have to register the parameter (interface) types passed to the constructor of the type you are trying to resolve, i.e. since I inject the IShellView interface into my ShellPresenter's constructor, I needed to register the IShellView type and not the IShellPresenter type:

public ShellPresenter(IShellView view) ...

I tested this by trying to resolve the type Tester:

Tester tester = Container.Resolve<Tester>();

As long as I inject SomeClass into its constructor:

public Tester(ISomeClass someClass)

I get unresolved dependency errors until I register SomeClass with the container:

Container.RegisterType<ISomeClass, SomeClass>();

Then it works. This is as surprising as it is educational. Needs to sink in. I'm going to go get a coffee and think about this for awhile.

If anyone can elaborate on why this is the case, it would be much appreciated.

Answer

Ray Henry picture Ray Henry · Apr 21, 2009

If you try to resolve a concrete class and have not registered an instance or sub-class to satisfy it, then Unity will construct an instance of the concrete class for you, resolving any dependencies that it has.

So when you ask for ShellPresenter, and haven't registered it, Unity just new's up a ShellPresenter for you with the ShellView as a parameter.