You have three problems here.
Problem 1. You're creating a new container:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
This container
will be empty and have 0 registrations. It's not the same container as you made your registrations to. There's a couple of ways to solve it:
Problem 1 - Solution 1: Don't inject the container. Inject the dependencies.
Instead of using the container you should inject your dependencies directly to your controller:
public class MyApiController : ApiController
{
IMasterDataClient _masterDataClient;
ILinksManager _linksManager
public MyApiController(IMasterDataClient masterDataClient, ILinksManager linksManager)
{
_masterDataClient = masterDataClient;
_linksManagerlinksManager;
}
}
This way you can avoid the service locator-pattern and your dependency to the container itself. If you're using named registrations you may need to use the Dependency
-attribute.
With Unity how do I inject a named dependency into a constructor?
Problem 1 - Solution 2: Inject your container instead of creating a new one.
If you really need your controller for some reason, then you should try to inject it instead. This way you will get the same container as you used for your registrations.
public class MyApiController : ApiController
{
IUnityContainer _container;
public MyApiController(IUnityContainer container)
{
_container = container;
}
}
Problem 1 - Solution 3: Keep an static reference to your container.
As a last resort you can keep your container as a static instance.
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
And in your registrations:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = IocContainer.Instance;
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Usage:
IocContainer.Instance.Resolve<IMasterDataClient>("MDS");
Problem 2. You don't seem to register the dependencies for MasterDataClient
.
It has dependencies for IApiClient
and IUriDispenser
. They need to be registered as well.
Problem 3. You assign your dependency resolver to the wrong container
You currently create two containers - myContainer
and container
. You make your registrations to one container, and then use another one as DependencyResolver
. You can solve it by removing myContainer
and only use container
. Otherwise you will not be able to use your registrations in Web Api.
public static class UnityConfig
{
public static void RegisterComponents()
{
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>();
container.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
container.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Update:
I don't know implementing classes for IApiClient and IUriDispenser as
it is third party dll so how can I register it
Unity needs to know which implementation to use when you resolve an interface. So somehow you need to tell Unity what implementation to use. There's an excellent answer from Mark Seemann in the question below:
Unity IoC for resolving assemblies dynamically
It scans the assembly for implementations of your interface and then registers them/it.
Alternatively you can use registration by convention, which enables you to do several registrations at once:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMapping.MatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
Note that this will register all implementations, including your own.
If you just want the third party implementations you should be able do do something like this:
// Get the assemblies where IApiClient exists.
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetTypes().Contains(typeof (IApiClient)));
// Register all implementations based on convention.
container.RegisterTypes(AllClasses.FromAssemblies(assemblies),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled); // Maybe another lifetime manager?
Update 2:
Make sure that the controller has a parameterless public constructor.
The error above can have many causes, most of them are covered in these questions:
Unable to inject DBContext into my Web API 2 Controller with Unity
Make sure that the controller has a parameterless public constructor error
error: Make sure that the controller has a parameterless public constructor webapi
Mostly it's Unity telling you that you're trying to resolve something that you didn't register. Or that you haven't registered a DependencyResolver at all.