2

我用 MVC3 构建了一个简单的票务跟踪系统。出于测试目的,我想实现 IOC/DI。现在我的控制器直接与数据库交互,这对 TDD 不利。我对这个主题很陌生。

现在我的 TicketDB.cs 模型看起来像这样:

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; } 
        }
}

我的 TicketController.cs 控制器看起来像这样:

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);
        }
    }
}

我看过一堆 IOC/DI 视频,但不太清楚如何实现它们。我知道我必须创建一个接口,以便我的控制器能够与数据库和静态数据列表进行交互。这看起来如何?

我在想我会Ninject用作 DI 框架,但我对其他建议持开放态度。

4

1 回答 1

1

使用Castle.Windsor

ITicketRepository:

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

TicketEf 存储库:

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);
    }

    ...    

票务控制器:

public class TicketsController : Controller
{
    private readonly ITicketRepository _ticketRepository;

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

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

    ...

ControllerInstaller:(按约定注册所有控制器)

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"));
    }
}

控制器工厂:

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);
    }
}    

全球.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>());
    }
}    
于 2013-09-19T23:14:27.050 回答