NInject and MVC 3 - Should I use DependencyResolver instead of [Inject] attribute?

2k views Asked by At

Recently I moved to MVC 3 and Ninject 2. In most of the code, I use constructor injection, but there are some places, where I had to use Inject attribute. Ninject 2 registers its own IDepencyResolver interface. I don't like DependencyResolver class being part of System.Web.Mvc namespace, because its function is not really strictly related to MVC, but now, when it is there, I can do

public SomeClass 
{
    public IUserService UserService { get; set; }

    public SomeClass()
    {
        UserService = DependencyResolver.Current.GetService<IUserService>();

instead of

public SomeClass 
{
    [Inject]
    public IUserService UserService { get; set; }

so I don't have to reference Ninject namespace in my classes. Should DependencyResolver be used like that?

3

There are 3 answers

3
Darin Dimitrov On BEST ANSWER

I use property injection only for dependencies that are not required for the proper working of the class but could add some functionality if the user sets them. Example of such functionality is logging. So you could have a property which represents a logger where the user can supply his own implementation and if he doesn't the class continues to work normally but it simply doesn't log.

For everything else I use constructor injection. This way you indicate to the consumer that this class has a required dependency on some other service.

So to answer your question about the property injection I would simply have:

public SomeClass 
{
    public IUserService UserService { get; set; }

    public void SomeMethodWhichDoesntEnforceUserService()
    {
        if (UserService != null)
        {
            // Provide some additional functionality
        }
    }
}

and if your class cannot function properly without the user service:

public SomeClass 
{
    private readonly IUserService _userService;
    public SomeClass(IUserService userService)
    {
        _userService = userService;
    }

    public void SomeMethodWhichRequiresTheService()
    {
        _userService.DoSomething();
    }
}

So in both cases no reference to any DI specifics. That's what Inversion of Control is all about.

3
Pero P. On

First question I would ask is why you can not perform constructor injection of the IUserService into SomeClass? It may indicate an issue with the design.

To avoid direct reference to the DependencyResolver you could implement some form of abstraction of a Service Locator over the DI framework, e.g. CommonServiceLocator, but as the answer to this question indicates, such abstractions shouldn't be necessary when doing DI correctly. Instead you should adjust the design of the application.

2
dotjoe On

I believe the ninject.web.mvc version for mvc3 now supports constructor injection on filter attributes. Have you tried it?