.NET MVC Dependency Injection with Ninject
Asked Answered
D

1

11

I've just started programming in .NET and I'm having some problems with implementing dependency injection (using Ninject).

I'm creating some sort of catering application where user can browse towns, in towns browse restaurants and in restaurants browse food.

I'm using UnitOfWork and repository pattern where for example I access town by id like this:

_unitOfWork.TownRepository.GetByID(id);

Now I started implementing services into application and I have encountered need for dependency injection.

I have created ITownService, IRestaurantService and IFoodService (since I've TownRepository, RestaurantRepository and FoodRepository in my UnitOfWork).

Sample look of TownService:

public class TownService : ITownService
    {
        // initialize UnitOfWork
        private IUnitOfWork _unitOfWork;

        public TownService()
            : this(new UnitOfWork())
        {
        }

        public TownService(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public Town GetByID(object id)
        {
            return _unitOfWork.TownRepository.GetByID(id);
        }

        public IEnumerable<Town> GetAll()
        {
            return _unitOfWork.TownRepository.Get();
        }

        public bool Insert(Town town)
        {
            // validation logic
            if (!ValidateTown(town))
                return false;

            try
            {
                _unitOfWork.TownRepository.Insert(town);
                _unitOfWork.Save();
            }
            catch
            {
                return false;
            }

            return true;
        }

        public bool Delete(object id)
        {
            try
            {
                _unitOfWork.TownRepository.Delete(id);
                _unitOfWork.Save();
            }
            catch
            {
                return false;
            }

            return true;
        }

        public bool Update(Town townToUpdate)
        {
            // validation logic
            if (!ValidateTown(townToUpdate))
                return false;

            try
            {
                _unitOfWork.TownRepository.Update(townToUpdate);
                _unitOfWork.Save();
            }
            catch
            {
                return false;
            }

            return true;
        } 
    }

I haven't implemented FoodService and RestaurantService yet, but they should be similar with of course some additinal methods exepct this that I have. For example in RestaurantService I might have public Restaurant GetRestaurantsInTown(Town town){} or something like that.

I hope that you got the feel of application a bit. Now lets back to Ninject.

In my TownController I would have something like this:

 public class TownController : Controller
    {

        private ITownService _townService;

        public TownController(ITownService townService)
        {
            _townService = townService;
        }
    }

Similar would be for RestaurantController and FoodController of course just constructor injecting.

How do I use Ninject in such example? Do I need some global IService and not ITownService, IRestaurantService and IFoodService which I'd inherid in TownService, RestaurantService and FoodService or is it okay like this?

When binding what do I need to bind?

kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<ITownService>().To<TownService>();
kernel.Bind<IRestaurantService>().To<RestaurantService>();
kernel.Bind<IFoodService>().To<TownService>();

Something like this?

In short - what I need for adding dependency injection with Ninject?

I'm really having problems with this and would need help.

Thanks a lot in forward.

Disobey answered 3/2, 2014 at 10:27 Comment(1)
Hi, Currently How you defined your constructor in the Controller? in above example you are passing only ITownService, what about IRestaurantService & IFoodService? how u r creating variable of these?Mascia
S
17

From the package manager console run this command:

Install-package Ninject.MVC3

This will add a class to App_Start/NinjectWebCommon.cs

If you look near the bottom there is a RegisterServices method.

You simply add the code from your question there i.e.

    private static void RegisterServices(IKernel kernel)
    {
      kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
      kernel.Bind<ITownService>().To<TownService>();
      kernel.Bind<IRestaurantService>().To<RestaurantService>();
      kernel.Bind<IFoodService>().To<TownService>();
    }
Satan answered 3/2, 2014 at 11:35 Comment(9)
Thats all that is needed?Mantra
@ŽeljaHuber Yes, that is the quickest way to get started. Sometimes if your project(s) become large people prefer to split out the activators into their own project. Did you get it working ok?Satan
Yeah this gave me great start, thanks a lot, still googling a bit how I might or might not change my Service Layer but I think I'm gonna go this way and implement Ninject as you wrote. Thanks alot again.Mantra
Just one question in above binding - Lets say i have 100 service classes and 100 Interface for each class then do I need to write 100 Kernel.Bind statement to bind Service to Interface ?Tyrontyrone
@pm86, Yes, you'll have to.Cockatoo
@Tyrontyrone You can use the Conventions extension to bind all types in an assembly. Will autobind IFoo to Foo for every interface in the assembly. See github.com/ninject/Ninject.Extensions.ConventionsPengelly
@Satan Thanks for the info. I have a doubt. I want to perform dependency injection for my Service and DataAccess files. If I am configuring both of them in the Web project, will this not affect my layered architecture? (Since I need to include my DataAccess Dlls here)Unbeliever
@RanjithV No problem, I'm sure there will be a way in Ninject to configure this in each project but you will need something to call it initially to set it up. If it is running from a web app you will need to do this either with an appstart class or some other means (OwinStartupAttribute).Satan
@Satan Thanks for the reply. I have solved this in a different way. I registered my services in a separate Project ( called "Infrastructure") and have loaded that assembly from the Web project usin Ninject.Unbeliever

© 2022 - 2024 — McMap. All rights reserved.