[ASP.NET
MVC Mavericks Road] 05 - Ninject 사용
[ASP.NET MVC Mavericks Road] 시리즈의 이전 기사(DI(종속성 주입) 및 Ninject )에서 ASP.NET
MVC에서 Ninject를 사용할 때 수행할 작업입니다. 이 기사에 이어 이 기사에서는 실제 예제를 사용하여 ASP.NET MVC에서 Ninject를 적용하는 방법을 보여줍니다.
이 글의 내용을 더 잘 이해하고 파악하기 위해 초보자는 이 글을 읽기 전에 DI(Dependency Injection)와 Ninject를 먼저 읽어보는 것이 좋습니다.
이 기사의 디렉토리:
준비 작업
BookShop이라는 새 빈 솔루션을 만듭니다. BookShop.WebUI라는 빈 MVC 애플리케이션과 BookShop.Domain이라는 클래스 라이브러리 프로젝트를 솔루션에 추가합니다. 디렉터리 구조는 다음과 같습니다.
두 프로젝트를 추가한 후 BookShop.WebUI 프로젝트 아래에 BookShop.Domain 프로젝트에 대한 참조를 추가합니다.
NuGet을 사용하여 BookShop.WebUI 프로젝트 및 BookShop.Domain 프로젝트용 Ninject 패키지를 각각 설치합니다. NuGet에 대한 소개는 DI(종속성 주입) 및 Ninject를 읽어보세요. 시각적 창을 통해 설치하거나 패키지
관리자 콘솔(보기->다른 Windows->패키지 관리자 콘솔)을 열고 다음 명령을 실행하여 설치할 수 있습니다.
Install-Package Ninject -Project BookShop.WebUI
Install-Package Ninject -Project BookShop.Domain
다음 그림은 성공적으로 설치되었음을 보여줍니다.
컨트롤러 팩토리 생성
ASP.NET MVC에서는 클라이언트 요청이 특정 컨트롤러의 작업에서 처리된다는 것을 알고 있습니다. 기본적으로 ASP.NET MVC는 기본 제공 Controller 팩토리 클래스 DefaultControllerFactory를 사용하여 특정 요청에 해당하는 Controller 인스턴스를 만듭니다. 때로는 기본 Controller 팩토리가 실제 요구 사항을 충족할 수 없으므로 이 기본 동작을 확장해야 합니다. 즉, DefaultControllerFactory 클래스에서 상속되는 사용자 정의 Controller 팩토리 클래스를 만들고 해당 메서드 중 일부를 재정의해야 합니다. 이를 위해 BookShop.WebUI 프로젝트 아래에 Infrastructure라는 폴더를 만들고 폴더에 NinjectControllerFactory라는 팩토리 클래스를 추가합니다. 위 코드의
public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { // todo:后面再来添加绑定 } }
ninjectKernel.Get (controllerType)은 컨트롤러 인스턴스를 가져올 수 있습니다. 여기서 Controller 클래스를 수동으로 인스턴스화하는 것은 매우 복잡한 프로세스입니다. Controller 클래스에 매개변수가 있는 생성자가 있는지 여부나 생성자의 매개변수 유형이 무엇인지 알 수 없습니다. Ninject를 사용하려면 위의 Get 메서드만 사용하면 됩니다. Ninject는 모든 종속성을 내부적으로 자동으로 처리하고 필요한 개체를 지능적으로 생성합니다.
Controller 팩토리 클래스가 생성된 후 NinjectControllerFactory 클래스를 사용하여 Controller 개체를 생성하도록 MVC에 지시해야 합니다. 이렇게 하려면 Global.asax 파일의 Application_Start 메서드에 다음 코드를 추가합니다. 🎜>
protected void Application_Start() { ...... //设置Controller工厂 ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); }여기에서는 위 코드의 원리에 대해서는 당분간 신경쓰지 않습니다. 커스텀 컨트롤러 팩토리를 설정하려면 여기에 등록해야 한다는 점만 알아두세요. 이 부분은 더 자세한 블로그 게시물에서 다루겠습니다.
MVC 애플리케이션에서는 모든 것이 도메인 모델을 중심으로 이루어집니다. 그래서 우리는 도메인 엔터티 모델을 저장하기 위해 BookShop.Domain 프로젝트에 Entities라는 폴더를 만들었습니다. 전자상거래 온라인 서점으로서 가장 중요한 도메인 주체는 당연히 Book입니다. 단지 시연용이므로 간단히 Book 클래스를 정의하고 이 클래스를 Entities 폴더에 추가합니다. 코드는 다음과 같습니다.
public class Book { public int ID { get; set; } public string Title { get; set; } public string Isbn { get; set; } public string Summary { get; set; } public string Author { get; set; } public byte[] Thumbnail { get; set; } public decimal Price { get; set; } public DateTime Published { get; set; } }
添加Repository
我们知道,我们肯定需要一种方式来从数据库中读取Book数据。在这我们不防为数据的使用者(这里指Controller)提供一个IBookRepository接口,在这个接口中声明一个IQueryable
public interface IBookRepository { IQueryable<Book> Books { get; } }
在MVC中我们一般会用仓储模式(Repository Pattern)把数据相关的逻辑和领域实体模型分离,这样对于使用者来说,通过调用仓储对象,使用者可以直接拿到自己想要的数据,而完全不必关心数据具体是如何来的。我们可以把仓储比喻成一个超市,超市已经为消费者供备好了商品,消费者只管去超市选购自己需要的商品,而完全不必关心这些商品是从哪些供应商怎么样运输到超市的。但对于仓储本身,必须要实现读取数据的“渠道”。
在BookShop.Domain工程中添加一个名为Concrete文件夹用于存放具体的类。我们在Concrete文件夹中添加一个实现了IBookRepository接口的BookRepository类来作为我们的Book数据仓储。BookRepository类代码如下:
public class BookRepository : IBookRepository { public IQueryable<Book> Books { get { return GetBooks().AsQueryable(); } } private static List<Book> GetBooks() { //为了演示,这里手工造一些数据,后面会介绍使用EF从数据库中读取。 List<Book> books = new List<Book>{ new Book { ID = 1, Title = "ASP.NET MVC 4 编程", Price = 52}, new Book { ID = 2, Title = "CLR Via C#", Price = 46}, new Book { ID = 3, Title = "平凡的世界", Price = 37} }; return books; } }
为了演示,上面是手工造的一些数据,后面的文章我将介绍使用Entity Framwork从数据库中读取数据。对于刚接触ORM框架的朋友可能对这里IQueryable感到奇怪,为什么用IQueryable作为返回类型,而不用IEnumerable呢?后面有机会讲Entity Framwork的时候再讲。
添加绑定
打开之前我们在BookShop.WebUI工程创建的NinjectControllerFactory类,在AddBindings方法中添加如下代码
private void AddBindings() { ninjectKernel.Bind<IBookRepository>().To<BookRepository>(); }
这句代码,通过Ninject把IBookRepository接口绑定到BookRepository,当IBookRepository接口的实现被请求时,Ninject将自动创建BookRepository类的实例。
到这里,Ninject的使用步骤就结束了,接下来我们把本示例剩余的步骤完成。
显示列表
右击BookShop.WebUI工程的Controllers文件夹,添加一个名为Book的Controller,按下面代码对其进行编辑:
public class BookController : Controller { private IBookRepository repository; public BookController(IBookRepository bookRepository) { repository = bookRepository; } }
在这,BookController的构造函数接受了一个IBookRepository参数,当BookController被实例化的时候,Ninject就为其注入了BookRepository的依赖。接下来我们为这个Controller添加一个名为List的Action,用来呈现Book列表。代码如下:
public class BookController : Controller { ... public ViewResult List() { return View(repository.Books); } }
当然我们需要添加一个View。右击上面的List方法,选择添加视图,在弹出的窗口进行如下配置:
然后我们在List.cshtml中用foreach循环来列举书本信息,代码如下:
@model IEnumerable<BookShop.Domain.Entities.Book> @{ ViewBag.Title = "Books"; } @foreach (var p in Model) { <div class="item" style="border-bottom:1px dashed silver;"> <h3>@p.Title</h3> <p>价格:@p.Price.ToString("c") </p> </div> }
最后我们还需要修改一下默认路由,让系统运行后直接导向到我们的{controller = "Book", action = "List"},打开Global.asax文件,找到RegisterRoutes方法,进行如下修改:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Book", action = "List", id = UrlParameter.Optional } ); }
到这,我们的程序可以运行了,效果如下:
결론:
이 기사는 ASP.NET MVC에서 Ninject를 사용하는 간단한 예입니다. MVC에서 Ninject를 사용하는 방법을 모든 사람에게 알리는 것이 목적입니다. 물론, Ninject의 힘은 이 기사에서 설명하는 것에만 국한되지 않습니다. Niject에 익숙해지면 MVC 애플리케이션을 구축할 때 확실히 좋아하게 될 것입니다.
위 내용은 [ASP.NET MVC Mavericks Road] 05 - Ninject 사용 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!