我用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框架,但我愿意接受其他建议。
答案 0 :(得分:1)
使用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:(按惯例注册所有控制器)
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>());
}
}