ASP.NET MVC 3: Dependency Injection โดยใช้ Ninject

เกริ่น

สวัสดีครับ… บทความนี้ผมจะแสดงขั้นตอนทำ Dependency Injection(DI) ง่ายๆด้วย Ninject  ใน projects web ที่พัฒนาด้วย ASP.NET MVC 3

บทความต้องอ่านก่อน

เครื่องมือต้องมีก่อน

1. Vistual Studio 2010

2. ASP.NET MVC 3.0 tool โหลดมาติดตั้งก่อนได้ที ASP.NET MVC 3

3. โหลดและติดตั้ง Ninject library จาก http://ninject.org/download

ลงมือประดิษฐ์กันเลย

1. เปิด visual studio 2010 ขึ้นมาครับ แล้ว New Project > Web > ASP.NET MVC 3 Web Application แล้วตั้งชื่อตามภาพข้างล่างนี้

2. เพิ่ม  interface IHomeServiceโดย click ขวาที่ project > Add > New Item > Code > Interface ตั้งชื่อว่า IHomeService.cs กด OK แล้วเติม code ข้างล่างนี้เข้าไป

public interface IHomeService
{
string Welcome(string name);
}

3. เพิ่ม class HomeService ที่ implement IHomeService โดย click ขวาที่ project > Add > Class … ตั้งชื่อว่า HomeService.cs กด OK แล้วเติม code ข้างล่างนี้เข้าไป

public class HomeService : IHomeService
{
int _counter = 0;
public string Welcome(string name)
{
++_counter;

return string.Format(“Hi. {0} count = {1}.”, name, _counter);
}

}

อธิบาย code นี้เล็กน้อย ก็คือ method Welcome รับ parameter เป็น string name เข้ามาแล้ว ก่อนจะคืนค่าออกไป ก็จะบวก _counter ไป 1 เพื่อนับจำนวน request ที่เรียก method Welcome จากที่ไหนก็แล้วแต่ใน web นี้ครับ

4. เพิ่ม class Controller โดย click ขวาที่ folder Controllers > Add > Controller… แล้วกำหนดค่าตามภาพครับ

ตั้งชื่อว่า HomeController เสร็จแล้วกด Add

5. เพิ่ม Code ข้างล่างนี้เข้าไปที่ file HomeController.cs ครับ

public class HomeController : Controller
{
IHomeService _homeService;
public HomeController(IHomeService homeService)
{
_homeService = homeService;
}

//
// GET: /Home/
public ActionResult Index()
{
ViewBag.Message = _homeService.Welcome(“Chav:P”);
return View();
}

}

6. เพิ่ม View Index โดย click ขวาที่ Action method Index ใน file HomeController.cs โดยตรงได้เลย ตามภาพข้างล่างนี้

เสร็จแล้วกด Add ครับ

7. หลังจาก Add view Index เข้ามาแล้ว ก็ไปแก้ไข view ที่ file Index.cshtml ที่อยู่ใน folder Views/Home/ นี้อีกเล็กน้อบครับ โดยผมจะให้มันแสดง ViewBag.Message ที่ได้จากการเรียก method Welcome จาก _homeService ที่ได้เตรียมไว้แล้ว จะ code ใน view แบบข้างล่างนี้

<h2>@ViewBag.Message</h2>

เอาละครับสรุปกันก่อนจากขั้นตอน 1-7 ข้างต้น ผมได้ สร้าง ASP.NET MVC projects ประกอบไปด้วย service class IHomeService.cs, HomeService.cs (มันก็คือ Dependency class) แล้วผมจะแสดงการ inject มันเข้าไปที่ Controller ที่จะแสดงในลำดับต่อไป ต่อจากนั้นผมได้เพิ่ม class HomeController.cs เพื่อเรียกใช้ method Welcome (ซึ่งมัน Dependent กับ IHomeService) แล้วผมก็กำหนดค่านี้เก็บไว้ใน ViewBag.Message ที่แสดงอยู่ใน Action Method Index และสุดท้ายผมก็ได้สร้าง View Index.cshtml เพื่อแสดงค่าที่เก็บอยู่ใน ViewBag.Message นี่เอง

ขั้นตอนต่อไปเป็นขั้นตอนสร้าง class ที่ทำหน้าที่ Dependency Injection ให้ IHomeService ของ HomeController โดยใช้ Ninject library ครับ

Dependency Injection โดยใช้ Ninject

1. เพิ่ม library Ninject เข้ามาครับโดยการ click ขวาที่ References เลือก Add Reference… แล้ว Browse ไปที่ folder ของ Ninject library ที่เราได้แตก zip ไว้แล้ว ตามภาพข้างล่างนี้ครับ

เลือก Ninject.dll แล้วกด OK

2. เพิ่ม class NinjectDependencyResolver.cs แล้ว implement IDependencyResolver แล้ว using package และ เติม code ตามข้างล่างนี้ลงไป

using Ninject;
using Ninject.Syntax;
using System.Web.Mvc;

public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IResolutionRoot _resolutionRoot;
public NinjectDependencyResolver(IResolutionRoot kernel)
{
_resolutionRoot = kernel;
}

public object GetService(Type serviceType)
{
return _resolutionRoot.TryGet(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)
{
return _resolutionRoot.GetAll(serviceType);
}
}

3. ไปที่ Global.asax เพิ่ม method WireUpComponents

private void WireUpComponents()
{
IKernel kernel = new StandardKernel();

kernel.Bind<IHomeService>().To<HomeService>();
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}

4. จากนั้นเรียก method WireUpComponents นี้ใน Application_Start

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

WireUpComponents();
}

5. เสร็จแล้วครับลอง run project นี้ขึ้นมาดูกันเลย ซึ่งมันจะแสดงคล้ายภาพข้างล่างนี้

จากภาพ ผมได้แสดงการ refresh page Index นี้ 3 ครั้งคุณจะเห็นว่า ค่า count เป็น 1 ตลอดเลยซึ่งผมไม่ต้องการแบบนี้ ผมต้องการให้มันนับเพิ่มไปที่ละ 1 ทุกครั้งที่เข้ามาที่หน้านี้ ผมก็เลยนึกถึง pattern หนึ่งที่สร้าง object แต่ตัวเดียวเท่านั้นไม่ว่าใครจะสร้างมัน มันมีชื่อว่า Singleton Pattenr นั่นเอง และ Ninject DI นี้ก็ช่วยผมได้เลยที่เดียวโดยผมแก้ไข code ที่ WireUpComponents อีกเล็กน้อย ดังนี้

private void WireUpComponents()
{
IKernel kernel = new StandardKernel();

kernel.Bind<IHomeService>().To<HomeService>().InSingletonScope();//กำหนดให้ HomeService สร้างแค่อันเดียวเท่านั้น
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}

build project แล้วลอง run ใหม่ครับ

จากภาพทุกๆครั้ง refresh page นี้ count ของผมก็จะบวกเพิ่มขึ้นไปทีละ 1 ตามต้องการ เพราะว่า HomeService ของผมนั้นถูกสร้างแค่ object เดียวเท่านั้น

เห็นแล้วใช่มั้ยครับว่าผมได้ implement Singleton Patterns ง่ายๆเพียงแค่ config Ninject DI ที่ method WireUpComponents โดยเรียก method InSingletonScope เพิ่มเข้าไปเพียงเท่านี้เอง ง่ายมากเลยใช่มั้ยละ!

Source Code

ขอบคุณครับ 😉

Advertisements

#asp-net, #design-patterns