کار با Ninject
بسم الله الرحمن الرحیم
آموزش dependency injection
این مطلب را برای تیم طراحی قرار دادم انشالله دوستان این تیم از آن استفاده نمایند.
چرا Ninject مفید است؟
بخش اعظمی از دست آوردهای به وجود آمده در حوزه نرم افزار از نسخه ابتدایی منتشر شده بدست می آید.
بیشتر زمان سرمایه گذاری شده در بخش تحلیل بعد از شروع به کار نرم افزار هزینه می شود.
باعث می شود تغییرات نرم افزار شما بسیار ساده تر انجام شود.
بعد از استفاده spring.net به مدت طولانی در asp.net به دنبال یک روش ساده تر و سریعتر و نه روشی بر پایه تریق وابستگی به صورت xml بودم. برای برنامه های MVC4 در نهایت به Ninject رسیدم چون رویکرد آن XML ای نیست و ساده است و استفاده از آن راحت است.
چطور تزریق کننده وابستگی را انتخاب کنیم؟
هر تزریق کننده مزایا و معایب خود را دارد و یک سری ویژگی را با خود به همراه دارد.
انتخاب یک تزریق کننده بستگی به مواردی دارد که شما بیشتر نیاز دارید دارد و این موضوع کاملا قابل بررسی است.
Ninject یک تزریق کننده متن باز است که برای NET. به وسیله Nate Kohari تولید شده است و یک سری ابزار مناسب به همراه دارد که همچنین ابزارهایی نیز برای MVC3 در آن قرارداده شده است. به هرحال، اگر شما هم مثل من به دنبال راه جدید هستید Ninject را دوست خواهید داشت.
چرا تزریق وابستگی؟
چند مورد از مزایای تزریق وابستگی بجای اینکه از لحاظ ماهیتی خود کلاس وابستگی داشته باشد به صورت زیر لیست شده اند:
- وابستگی تحمیل شده را کاهش می دهد، ایجاد انعطاف در پیاده سازی جایگزین برای یک سرویس مشخص بدون نیاز به کامپایل مجدد
- اتصال سست بین کلاس ها با استفاده کردن از interface
- کدها قابلیت استفاده مجدد، قابلیت تست، قابلیت خواندن، بیشتر پیدا می کنند
اضافه کردن Ninject
ninject را به پروژه اضافه کنید و سپس به دنبال آن فایل های زیر را نیز باید اضافه شود:
- Ninject.dll
- Ninject.Web.Common.dll
- Ninject.Web.Mvc.dll
کد کنترلر را با تعریف یک متغییر read-only برای سرویس خودتان و تابع سازنده را با معرفی کردن پارامتر سرویس نمونه (منظورم instance است) مانند زیر تغییر دهید:
namespace NinjectMvc4.Controllers
{
public class HomeController : Controller
{
private readonly IMessageService _messageService;
public HomeController(IMessageService messageService)
{
_messageService = messageService;
}
public ActionResult Index()
{
ViewBag.Message = _messageService.GetWelcomeMessage();
return View();
}
}
}
در اینجا ما یک اینترفیس با نام IMesssageService داریم و می خواهیم messageService_ را در MessageService به وسیله Ninject تزریق کنیم.
namespace NinjectMvc4.ServiceLayer
{
public class MessageService:IMessageService
{
public string GetWelcomeMessage()
{
return "Welcome to Ninject MVC4 Example";
}
}
}
تغییرات فایل Global.asax:
کلاس MvcApplication از کلاس انتزاعی NinjectHttpApplication ارث می برد که این کلاس قسمتی از فضای نامی Ninject.Web.Common است.
متد CreateKernel را به صورت زیر پیاده سازی می کنیم.
یک شی از StandardKernel ایجاد می کنیم، بارگذاری اسمبلی های قابل اجرا در kernel را انجام می دهد. ارتباط بین Interface سرویس و پیاده سازی تزریق شده:
در این مثال، درحالی که کنترلری را با تزریق نمونه ای از MessageService درون سازنده HomeController می سازید، می توان آن را به متغیر messageService_ تخصیص داد.
namespace NinjectMvc4
{
public class MvcApplication : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind().To();
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
متد OnApplicationStarted را برای ثبت Filters, routes ,bundles در پروژه Override می کنیم. MVC4 به صورت استاندارد از Application_Start در زمانی که از Ninject استفاده نمی شود، استفاده می کند.
کار تمام شد، حال نرم افزار را اجرا می کنیم و پیغامی را که نوشته ایم را از MessageService که به HomeController تزریق کرده ایم دریافت می کنیم.
Ninject با MVC4 ادغام شده اما تفاوتی ندارد حتی اگر MVC3 هم استفاده کنید.
اگر می خواهید در asp.net webapi از تزریق وابستگی استفاده کنید باید از DependencyResolver استفاده کنید می بایست:
System.Web.Http.Dependencies.IDependencyResolver این را پیاده سازی کنید.
چرا؟ زیرا Ninject’s Dependency Resolver جاری با پیاده سازی System.Web.Mvc.IDependencyResolver نمی توان به GlobalConfiguration.Configuration از برنامه WebApi اختصاص داد، این انتظارات یک نمونه از System.Web.Http.Dependencies.IDependencyResolver بجای System.Web.Mvc.IDependencyResolver است
public class LocalNinjectDependencyResolver :
System.Web.Http.Dependencies.IDependencyResolver
{
private readonly IKernel _kernel;
public LocalNinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable< object > GetServices(Type serviceType)
{
try
{
return _kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List< object >();
}
}
public void Dispose()
{
// When BeginScope returns 'this', the Dispose method must be a no-op.
}
}
متد CreateKernel را مانند زیر برای اختصاص دادن یک نمونه از LocalNinjectDependencyResolver به GlobalConfiguration تغییر می دهیم :
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
GlobalConfiguration.Configuration.DependencyResolver = new LocalNinjectDependencyResolver(kernel);
return kernel;
}
نظرات (۲)
با عرض سلام
پاسخ به سوال شما خیلی مشکل است، زیرا تعریف خوب و بد، در شرایط و موقعیت های متفاوت ممکن است تغییر کند، شما باید ببیند از ابزارتان چه انتظاراتی دارید.
یاعلی
باعرض سلام
نظر لطف شما است، همه ی ما در اینجا هستیم تا دانشمان را به اشتراک بگذاریم.
دقیقا بنده نیز با حرف شما موافق هستم.
همچنین شاید این مطلب بتواند به شما کمک کند
http://ably.ir/post/unity-castle-windsor-structuremap-ninject-who-has-best-performance
موفق باشید
به نظرتون استفاده از StructureMap بهتر است یا Ninject ؟