Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?
Asked Answered
E

7

47

In my bootstrapper:

namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
    public static class Initializer
    {
        private static bool isInitialize;
        private static readonly object LockObj = new object();
        private static IUnityContainer defaultContainer = new UnityContainer();

        static Initializer()
        {
            Initialize();
        }

        public static void Initialize()
        {
            if (isInitialize)
                return;

            lock (LockObj)
            {
                IUnityContainer container = defaultContainer;

                //registering Unity for MVC
                DependencyResolver.SetResolver(new UnityDependencyResolver(container));

                //registering Unity for web API
                //  GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);

                #region managers
                container.RegisterType<ISettingsManager, SettingsManager>();

                container.RegisterType<IMamDataManager, MamDataManager>();

                container.RegisterType<IAppsDataManager, AppsDataManager>();
                #endregion

                if (!isInitialize)
                {
                    isInitialize = true;
                }
            }
        }
    }
}

in my controller's code:

ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();

hovering on mUnityContainer I see ISettingsManager is mapped to SettingsManager

but then I get the error:

Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?

I have also tried

ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));

but no use

Erma answered 27/1, 2013 at 15:59 Comment(14)
Is container and mUnityContainer the same object?Garrote
What's the point of using Dependency Injection if in your controller code you write ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();? This completely defeats the purpose of dependency injection.Bannerman
yes. And also when debugging I see ISettingsManager is registered to SettingsManagerErma
@DarinDimitrov DI is useful for decoupling interface from implementation; injection of the value to avoid manual lookup is merely "sugar on top".Crumhorn
@Darin Dimitrov ISettingsManager is a member, why should I create a member for it?Erma
@MortenMertner, I think you completely misunderstand the concept of Dependency Injection. Elad Benda, I don't quite understand your question. Your controller should simply take an ISettingsManager argument. The injection will be performed by the DI framework. You should never be calling container.Resolve<> anywhere from your code. Otherwise you are defeating the whole purpose of dependency injection.Bannerman
@DarinDimitrov DI is a poor (but common) name for the "Inversion of Control" pattern. Injection of values from the outside is not a prerequisite to decoupling. Go look it up: en.wikipedia.org/wiki/Inversion_of_controlCrumhorn
@Darin Dimitrov you mean the injection should only happen in the ctor. But what about local variables in some functions?Erma
@MortenMertner, I think you are confusing the patterns Service Locator and Dependency Injection (Inversion Of Control).Bannerman
@EladBenda, you could also use property injection for non-required dependencies. It's a less common scenario though.Bannerman
@DarinDimitrov No need to argue here, but you are wrong. See the Wikipedia article linked above. PM me if you feel a need to continue.Crumhorn
@Darin Dimitrov I use this injection, as their ctor is long and full with dependencies I want the container to resolve by itselfErma
@EladBenda, that's not an injection. Please do not confuse the notions. What you use is called Service Locator. It's a different pattern, often referred to as an anti-pattern. There's nothing wrong with having many dependencies. It means that in order for this class to work properly he needs many dependencies. Add them to the constructor and leave the wiring happen from the outside.Bannerman
Service Locator pattern is not universally an anti-pattern, nor is constructor injection the entirety of implementing DI; it is an ideal that works well on instances that are constructed with the DI container but any DI container that supports constructor injection must still resolve a bootstrap-established definition of an interface. Some of us are using DI container only for bootstrap-defining implementations of abstract interfaces. You're wasting people's time here by beating around the question.Thiamine
B
19

You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:

public class HomeController: Controller
{
    private readonly ISettingsManager settingsManager;
    public HomeController(ISettingsManager settingsManager)
    {
        this.settingsManager = settingsManager;
    }

    public ActionResult Index()
    {
        // you could use the this.settingsManager here
    }
}

As you can see in this example the controller doesn't know anything about the container. And that's how it should be.

All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.

As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.

Bannerman answered 27/1, 2013 at 16:31 Comment(5)
what about local variables in some functions? al of them should become memebers? I think that's a bad practice. no?Erma
What do you mean by local variables in functions? If some class requires external dependencies then those dependencies should be abstracted away in an interface that gets injected into this class. That's how Dependency Injection (Inversion of Control) works. The concrete type that gets injected into the class is not the responsibility of the class. The wiring should happen from the outside.Bannerman
This doesn't answer the question. This "answer" only speaks to toss out the merit of the question itself; it belongs in comments only. The "best practices" discussion on patterns belongs in programmers.stackexchange.com.Thiamine
How do you suggest we resolve dependencies in Global.asax.cs file? Surely we can't inject it into the constructor. This answer is outright wrong and misinformativeCaporal
The increase of parameters in the constructor could lead to a performance issue, if you depend on 1000 of classes I recommend to resolve the concrete type when you are gonna to use it, not injecting them via the constructorRains
C
53

Just for others (like me) who might have faced the above error. The solution in simple terms.

You might have missed to register your Interface and class (which implements that inteface) registration in your code.

e.g if the error is
"The current type, xyznamespace. Imyinterfacename, is an interface and cannot be constructed. Are you missing a type mapping?"

Then you must register the class which implements the Imyinterfacename in the UnityConfig class in the Register method. using code like below

 container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
Closed answered 8/7, 2015 at 2:4 Comment(5)
Thank you buddy.. You save my lots of time.Gyneco
Thanks. Explained very well. :)Ashmead
I had hard time for this and got this solution working. My requirement was to configure Unity from web.config and it seems previous version(archive.codeplex.com/?p=unity) of Unity was able to do so but for new Unity ( github.com/unitycontainer ) needs extra efforts by using Unity.Mvc5 & Unity.WebApi. devtrends.co.uk/blog/… #609085Seraglio
This is the best answer for this issue.Character
I have an issue where my xyznamespace. Imyinterfacename is implemeted by another interface "Interface2" and am receiving the same error . Should i do the same ? container.RegisterType<Imyinterfacename, Interface2>();Thanasi
B
19

You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:

public class HomeController: Controller
{
    private readonly ISettingsManager settingsManager;
    public HomeController(ISettingsManager settingsManager)
    {
        this.settingsManager = settingsManager;
    }

    public ActionResult Index()
    {
        // you could use the this.settingsManager here
    }
}

As you can see in this example the controller doesn't know anything about the container. And that's how it should be.

All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.

As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.

Bannerman answered 27/1, 2013 at 16:31 Comment(5)
what about local variables in some functions? al of them should become memebers? I think that's a bad practice. no?Erma
What do you mean by local variables in functions? If some class requires external dependencies then those dependencies should be abstracted away in an interface that gets injected into this class. That's how Dependency Injection (Inversion of Control) works. The concrete type that gets injected into the class is not the responsibility of the class. The wiring should happen from the outside.Bannerman
This doesn't answer the question. This "answer" only speaks to toss out the merit of the question itself; it belongs in comments only. The "best practices" discussion on patterns belongs in programmers.stackexchange.com.Thiamine
How do you suggest we resolve dependencies in Global.asax.cs file? Surely we can't inject it into the constructor. This answer is outright wrong and misinformativeCaporal
The increase of parameters in the constructor could lead to a performance issue, if you depend on 1000 of classes I recommend to resolve the concrete type when you are gonna to use it, not injecting them via the constructorRains
U
10

In my case, I was getting this error despite registering an existing instance for the interface in question.

Turned out, it was because I was using Unity in WebForms by way of the Unity.WebForms Nuget package, and I had specified a Hierarchical Lifetime manager for the dependency I was providing an instance for, yet a Transient lifetime manager for a subsequent type that depended on the previous type - not usually an issue - but with Unity.WebForms, the lifetime managers work a little differently... your injected types seem to require a Hierarchical lifetime manager, but a new container is still created for every web request (because of the architecture of web forms I guess) as explained excellently in this post.

Anyway, I resolved it by simply not specifying a lifetime manager for the types/instances when registering them.

i.e.

container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());    
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());

becomes

container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();

So that IMapper can be resolved successfully here:

public class UserContext : BaseContext, IUserContext
{
    public UserContext(IMapper _mapper) : base(_mapper)
    {

    }
    ...
}
Urial answered 15/5, 2016 at 20:28 Comment(0)
D
0

May be You are not registering the Controllers. Try below code:

Step 1. Write your own controller factory class ControllerFactory :DefaultControllerFactory by implementing defaultcontrollerfactory in models folder

  public class ControllerFactory :DefaultControllerFactory
    {
    protected override IController GetControllerInstance(RequestContext         requestContext, Type controllerType)
        {
            try
            {
                if (controllerType == null)
                    throw new ArgumentNullException("controllerType");

                if (!typeof(IController).IsAssignableFrom(controllerType))
                    throw new ArgumentException(string.Format(
                        "Type requested is not a controller: {0}",
                        controllerType.Name),
                        "controllerType");

                return MvcUnityContainer.Container.Resolve(controllerType) as IController;
            }
            catch
            {
                return null;
            }

        }
        public static class MvcUnityContainer
        {
            public static UnityContainer Container { get; set; }
        }
    }

Step 2:Regigster it in BootStrap: inBuildUnityContainer method

private static IUnityContainer BuildUnityContainer()
    {
      var container = new UnityContainer();

      // register all your components with the container here
      // it is NOT necessary to register your controllers

      // e.g. container.RegisterType<ITestService, TestService>();    
      //RegisterTypes(container);
      container = new UnityContainer();
      container.RegisterType<IProductRepository, ProductRepository>();


      MvcUnityContainer.Container = container;
      return container;
    }

Step 3: In Global Asax.

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
            Bootstrapper.Initialise();
            ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));

        }

And you are done

Dray answered 5/2, 2016 at 14:1 Comment(0)
T
0

In my case, I have used 2 different context with Unitofwork and Ioc container so i see this problem insistanting while service layer try to make inject second repository to DI. The reason is that exist module has containing other module instance and container supposed to gettng a call from not constractured new repository.. i write here for whome in my shooes

Tijuanatike answered 26/4, 2016 at 7:13 Comment(0)
T
0

I had this problem, and the cause was that I had not added the Microsoft.Owin.Host.SystemWeb NuGet package to my project. Although the code in my startup class was correct, it was not being executed.

So if you're trying to solve this problem, put a breakpoint in the code where you do the Unity registrations. If you don't hit it, your dependency injection isn't going to work.

Tula answered 17/7, 2018 at 12:52 Comment(0)
F
0

Below code will be helpful for you

public static IUnityContainer Initialise(IUnityContainer container = null)
{
    if (container == null)
    {
        container = new UnityContainer();
    }
    container.RegisterType<ISettingsManager, SettingsManager>();
    container.Resolve<SettingsManager>();
    container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
    return container;
}
Fertilize answered 6/8, 2018 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.