0

I have the following class and interface definitions:

interface IView { ... }

interface IViewA : IView { ... }
interface IViewB : IView { ... }

class ViewA : IViewA { ... }
class ViewB : IViewB { ... }

class Controller
{
     public Controller(IViewA view) { ... }
}

And I register them in the unity container like this:

unityContainer.RegisterSingleton<IViewA, ViewA>("TheTestViewA");
unityContainer.RegisterSingleton<IViewB, ViewB>("TheTestViewB");
unityContainer.RegisterSingleton<Controller>();

However when I then request the instance of the controller, unity throws an exception.

unityContainer.Resolve<Controller>();

Resolution failed with error: No public constructor is available for type IViewA.

It seems that it wants to construct the interface and not the class. I also found out, that when I omit the naming parameter "TheTestViewA" it works fine. However I need that parameter because later on I need to container.ResolveAll<IView>() which only works when the mapping has a name. ( ResolveAll not working )

4
  • Is there only one concrete of IView (the "View" you provide?) or other concretes of IView? Why do you need to call ResolveAll? Commented Jul 15, 2021 at 11:17
  • @granadaCoder, yes there are several implementations of IView, i will edit the question accordingly. Commented Jul 15, 2021 at 11:38
  • So I would suggest that you do not use the "ServiceLocator" pattern...where you pull out the (n concretes) from the IoC container. But rather you inject them as needed. Please look at this answer : stackoverflow.com/questions/42402064/… The 3 concretes I have are disambiguated......but does not use ServiceLocator. Commented Jul 15, 2021 at 14:27
  • Also (next to my answer) read the "Steven" answer.....he outlines the why very well. Commented Jul 15, 2021 at 14:32

1 Answer 1

2

The exception is confusing, but what happens is that Unity can't find a registration for IView. For it to be able to inject an IView into Controller, it requires a nameless registration for IView, but all it has is a named registration (TheTestViewA).

Since a registration for IView is missing, Unity assumes IView is a concrete type and tries to instantiate it. But IView has no constructors (because its an interface), hence the exception.

You can try the following code instead:

var unityContainer = new UnityContainer();

unityContainer.RegisterSingleton<ViewA>();
unityContainer.RegisterSingleton<IViewA, ViewA>();
unityContainer.RegisterSingleton<IViewB, ViewB>();
            
unityContainer.RegisterFactory<IView>("A", c => c.Resolve<IViewA>(), new SingletonLifetimeManager());
unityContainer.RegisterFactory<IView>("B", c => c.Resolve<IViewB>(), new SingletonLifetimeManager());

unityContainer.RegisterSingleton<Controller>();
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, that will avoid the exception, but later when calling ResolveAll<IView> I will get an empty list instead of all singletons that implement IView.
Ha! I just put the ioc jedi master reference in the comments "See 'Steven' answer".. and here you are!
The updated solution partially works, but the problem with this is, that it creates two Singletons of ViewA and ViewB, while I want to have only one. i.e. the two registrations should return the same instance of ViewA and ViewB.
@clamp: I'm sorry about that. Updated my question again. I got confused by how Unity handles deduplication of registrations. It seems t hat named registrations get their own lifetime manager. This is different when making multiple unnamed registrations for the same concrete type (e.g. c.RegisterSingleton<IA, A>(); c.RegisterSingleton<A>();). In the latter case you get one instance (e.g. c.Resolve<A>() == c.Resolve<IA>()).
That works, thanks! Just one more question: can the instance of SingletonLifeTimeManager be the same for all factories or does each need its own?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.