Unity: Cannot register type from different assembly
-
13-06-2021 - |
Question
I'm trying to implement Dependency injection
in my MVC application. I'm using Unity.Mvc3.dll
for IoC. I just wondering how the Unity can't register Types from another assembly. Here's the code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
// ok: register type from this assembly
container.RegisterType<IMessages, Messages>();
// fail: register type from another assembly (service reference)
container.RegisterType<IPlayerService, PlayerService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception ex)
{
throw ex;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (Exception ex)
{
throw ex;
}
}
}
Usage in the MVC Controller:
[Dependency]
public IPlayerService PlayerService { get; set; }
[Dependency]
public IMessages Messages { get; set; }
public ActionResult Index()
{
PlayerMessageViewModel vm = new PlayerMessageViewModel();
vm.Messages = Messages; // success!
vm.Players = PlayerService.Get(); // fail: null reference exception :PlayerService
return View(vm);
}
PlayerService
is always null while the Messages is OK.
Here is the PlayerService
Class
public class PlayerService : IPlayerService
{
private readonly MyDbEntities _dbContext;
public PlayerService()
{
_dbContext = new MyDbEntities();
}
public PlayerService(MyDbEntities dbContext)
{
_dbContext = dbContext;
}
public IQueryable<Player> Get()
{
return _dbContext.Players.AsQueryable();
}
}
this is the complete Error Message
Resolution of the dependency failed, type = "System.Web.Mvc.IControllerFactory", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed. Are you missing a type mapping?
Solution
By default unity picks the constructor with the most parameters, so I think it'll be trying to use the second constructor with the dbContext parameter, which it can't resolve. If you mark your default constructor with the attribute [InjectionConstructor] then hopefully that will solve your problem
OTHER TIPS
You are hiding all exceptions with catch { return null; }
try to remove it and see what exception is thrown while resolving. I think exception is thrown in PlayerService
constructor.
EDIT:
When an MVC application starts for the first time, the dependency resolver is called with the following types in the following order:
- IControllerFactory
- IControllerActivator
- HomeController
If you did not implement your resolver to return null if a type is not registered then you will probably end up seeing an error similar to:
The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed
You are violating the contract of IDependencyResolver
. It should return null
for types which can not be resolved. The problem with Unity is that it tries to build all classes that it can find, no matter if they are registered in the container or not.
Hence a class somewhere can not be built.
There is also a Unity.Mvc3
package available in nuget.
The current type, (EX-DI.IBLL.IEmployee), is an interface and cannot be constructed. Are you missing a type mapping?
Ans - Just in Unity.config.cs
add the following thye
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
**container.RegisterType<IEmployee,EmployeeManager>();**
//this could be your interface and the class implementing the interface.
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}