简体   繁体   中英

Implementing IOC/ Dependency injection in a simple mvc3 project

I built a simple ticket-tracking system with MVC3. For testing purposes, I'd like to implement IOC/DI. Right now my controller interacts directly with the database, which is bad for TDD. I'm quite new to the subject.

Right now my TicketDB.cs Model looks like this:

namespace TicketTracker.Models
{
    public class TicketDB
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }

    }

        public class TicketDBContext : DbContext
        {
        public DbSet<TicketDB> Tickets { get; set; } 
        }
}

And my TicketController.cs controller looks like this :

namespace TicketTracker.Controllers
{ 
    public class TicketsController : Controller
    {
        private TicketDBContext db = new TicketDBContext();

    //
    // GET: /Tickets/

        public ViewResult Index()
        {
            return View(db.Tickets.ToList());
        }

        //
        // GET: /Tickets/Details/5

        public ViewResult Details(int id)
        {
            TicketDB ticketdb = db.Tickets.Find(id);
            return View(ticketdb);
        }

        //
        // GET: /Tickets/Create

        public ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /Tickets/Create

        [HttpPost]
        public ActionResult Create(TicketDB ticketdb)
        {
            if (ModelState.IsValid)
            {
                db.Tickets.Add(ticketdb);
                db.SaveChanges();
                return RedirectToAction("Index");  
            }

            return View(ticketdb);
        }

        //
        // GET: /Tickets/Edit/5

        public ActionResult Edit(int id)
        {
            TicketDB ticketdb = db.Tickets.Find(id);
            return View(ticketdb);
        }

        //
        // POST: /Tickets/Edit/5

        [HttpPost]
        public ActionResult Edit(TicketDB ticketdb)
        {
            if (ModelState.IsValid)
            {
                db.Entry(ticketdb).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(ticketdb);
        }

    //
    // GET: /Tickets/Delete/5

        public ActionResult Delete(int id)
        {
            TicketDB ticketdb = db.Tickets.Find(id);
            return View(ticketdb);
        }

    //
        // POST: /Tickets/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {            
            TicketDB ticketdb = db.Tickets.Find(id);
            db.Tickets.Remove(ticketdb);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

I've watched a bunch of IOC/DI videos, but can't quite figure out how to implement them. I know I have to create an interface, so my controller will be able to interact with both a database, and a static list of data. How would this look?

I was thinking I'd use Ninject as the DI framework, but I am open to other suggestions.

Using Castle.Windsor

ITicketRepository:

public interface ITicketRepository
{
    IList<Ticket> FindAll();
    Ticket Find(int id);
    void Save(Ticket ticket);
}

TicketEfRepository:

public class TicketEfRepository: ITicketRepository
{
    public IList<Ticket> FindAll()
    {
       var db = new TicketDBContext();
       return db.Tickets.ToList();
    }

    public Ticket Find(int id)
    {
       var db = new TicketDBContext();
       return db.Tickets.Find(id);
    }

    ...    

TicketsController:

public class TicketsController : Controller
{
    private readonly ITicketRepository _ticketRepository;

    public TicketsController(ITicketRepository ticketRepository) 
    {
        _ticketRepository = ticketRepository;
    }

    public ViewResult Index()
    {
        return View(_ticketRepository.FindAll());
    }

    ...

ControllerInstaller: (Registers all controllers by convention)

public class ControllerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(FindControllers().Configure(ConfigureControllers()));
        container.Register(
            Component
                .For<IControllerFactory>()
                .ImplementedBy<ControllerFactory>()
                .LifeStyle.Singleton
        );
    }

    private ConfigureDelegate ConfigureControllers()
    {
        return c => c.LifeStyle.Transient;
    }

    private BasedOnDescriptor FindControllers()
    {
        return AllTypes.FromAssemblyContaining<TicketsController>()
            .BasedOn<IController>()
            .If(t => t.Name.EndsWith("Controller"));
    }
}

ControllerFactory:

public class ControllerFactory : DefaultControllerFactory
{
    private readonly IKernel kernel;

    public ControllerFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public override void ReleaseController(IController controller)
    {
        kernel.ReleaseComponent(controller);
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException(404,
                                    string.Format("The controller for path '{0}' could not be found.",
                                                  requestContext.HttpContext.Request.Path));
        }
        return (IController) kernel.Resolve(controllerType);
    }
}    

Global.asax :

public class MvcApplication : HttpApplication
{
    private static IWindsorContainer _container;

    protected void Application_Start()
    {
        BootstrapContainer();
    }

    protected void Application_End(object sender, EventArgs e)
    {
        _container.Dispose();
    }

    private void BootstrapContainer()
    {
        _container = new WindsorContainer();

        // Registers all components from classes implementing 
        // IWindsorInstaller when classes defined in the web assembly, i.e.
        // ControllerInstaller
        _container.Install(FromAssembly.This());

        // You can also put this in a separate installer class and register
        // by convention
        _container.Register(
            Component
                .For<ITicketRepository>()
                .ImplementedBy<TicketEfRepository>()
                .LifeStyle.Transient);

        ControllerBuilder.Current.SetControllerFactory(
                _container.Resolve<IControllerFactory>());
    }
}    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM