46

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

Elad Benda
  • 35,076
  • 87
  • 265
  • 471
  • Is `container` and `mUnityContainer` the same object? – Jon Jan 27 '13 at 16:19
  • 2
    What's the point of using Dependency Injection if in your controller code you write `ISettingsManager sm = mUnityContainer.Resolve();`? This completely defeats the purpose of dependency injection. – Darin Dimitrov Jan 27 '13 at 16:19
  • yes. And also when debugging I see `ISettingsManager` is registered to `SettingsManager` – Elad Benda Jan 27 '13 at 16:21
  • @DarinDimitrov DI is useful for decoupling interface from implementation; injection of the value to avoid manual lookup is merely "sugar on top". – Morten Mertner Jan 27 '13 at 16:22
  • @Darin Dimitrov ISettingsManager is a member, why should I create a member for it? – Elad Benda Jan 27 '13 at 16:22
  • 1
    @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. – Darin Dimitrov Jan 27 '13 at 16:22
  • 4
    @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: http://en.wikipedia.org/wiki/Inversion_of_control – Morten Mertner Jan 27 '13 at 16:25
  • @Darin Dimitrov you mean the injection should only happen in the ctor. But what about local variables in some functions? – Elad Benda Jan 27 '13 at 16:25
  • 1
    @MortenMertner, I think you are confusing the patterns `Service Locator` and `Dependency Injection (Inversion Of Control)`. – Darin Dimitrov Jan 27 '13 at 16:27
  • 1
    @EladBenda, you could also use property injection for non-required dependencies. It's a less common scenario though. – Darin Dimitrov Jan 27 '13 at 16:27
  • 1
    @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. – Morten Mertner Jan 27 '13 at 16:28
  • @Darin Dimitrov I use this injection, as their ctor is long and full with dependencies I want the container to resolve by itself – Elad Benda Jan 27 '13 at 16:44
  • 1
    @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. – Darin Dimitrov Jan 27 '13 at 16:46
  • 2
    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. – Jon Davis Oct 27 '14 at 19:06

7 Answers7

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>();
Ram
  • 15,908
  • 4
  • 48
  • 41
  • 1
    Thank you buddy.. You save my lots of time. – Pawan Ratre Jul 07 '17 at 07:37
  • Thanks. Explained very well. :) – Dev Jul 24 '17 at 10:53
  • 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(https://archive.codeplex.com/?p=unity) of Unity was able to do so but for new Unity ( https://github.com/unitycontainer ) needs extra efforts by using Unity.Mvc5 & Unity.WebApi. https://www.devtrends.co.uk/blog/using-unity.mvc5-and-unity.webapi-together-in-a-project https://stackoverflow.com/questions/608585/can-someone-explain-microsoft-unity – Saurabh Aug 12 '18 at 13:11
  • This is the best answer for this issue. – Ranch Camal Oct 06 '18 at 06:32
  • 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(); – Mr.Curious May 30 '22 at 07:17
20

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.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • what about local variables in some functions? al of them should become memebers? I think that's a bad practice. no? – Elad Benda Jan 27 '13 at 16:43
  • 1
    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. – Darin Dimitrov Jan 27 '13 at 16:44
  • 18
    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. – Jon Davis Oct 27 '14 at 19:07
  • 5
    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 misinformative – Joe Phillips Nov 28 '16 at 22:33
  • 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 constructor – Zinov Nov 29 '17 at 21:28
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)
    {

    }
    ...
}
Community
  • 1
  • 1
Breeno
  • 3,007
  • 2
  • 31
  • 30
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

GrandMasterFlush
  • 6,269
  • 19
  • 81
  • 104
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

Hamit YILDIRIM
  • 4,224
  • 1
  • 32
  • 35
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.

Dominic Cronin
  • 6,062
  • 2
  • 23
  • 56
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;
}
Aswin A
  • 104
  • 10
Balamurugan
  • 137
  • 1
  • 1
  • 13