اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
دو دقیقه
همانطور که میدانید ASP.NET Core از تزریق وابستگیها ( Dependency Injection ) پشتیبانی میکند، که یک نوع Design Pattern است، و در اصل یک تکنیک است برای دستیابی و پیاده سازی اصل Inversion Of Control یا همان IoC بین کلاسها و وابستگیهای آن کلاسها. متد ConfigureServices در کلاس Startup وظیفهای دارد برای ثبت و تعریف سرویسهای مورد استفادهی در برنامه از جمله Platform Features مانند EF Core و معماری MVC. این متد در اصل DI Container ما است و میتوانیم از آن برای loosely coupled کردن برنامه مان از آن استفاده کنیم. در این متد 3 روش برای ثبت و تعریف سرویسهای ما وجود دارد، که این 3 روش در اصل طول عمر ( حیات ) یک سرویس را مشخص میکنند. در پایین نام این سه LifeTime را برای شما لیست میکنم:
- Transient
- Scoped
- Singleton
تزریق وابستگی را در برنامههای ASP.NET Core میتوان به چند طریق انجام داد:
- Constructor Injection
- Property Injection
- Method Injection
- Action & Handler Injection
که بیشترین نوع استفاده از طریق سازندهی کلاس یا همان Constructor است ( نوع اول ).
در این مقاله میخواهیم مورد چهارم را مورد بررسی قرار دهیم، که برای تزریق مستقیم وابستگی به یک Handler Method یا Action Method استفاده میشود؛ بدون تزریق وابستگی به سازنده و ساخت فیلد خصوصی و readonly از Abstraction مورد نظر. مایکروسافت این نوع تزریق را به صورت یک Attribute در آورده است، که از کلاس Attribute هم ارث بری کرده است و در فضای نام
Microsoft.AspNetCore.Mvc
خب نحوه استفاده از این Attribute را در ادامه یاد خواهیم گرفت. همانطور که در بالا گفته شد، با استفاده از این صفت دیگر نیازی به تزریق وابستگی در سازنده ندارید؛ البته از این صفت مواقعی استفاده میشود که برای مثال فقط در یک اکشن متد یا هندلر متد میخواهید استفاده کنید.
مثال واقعی:
فرض کنید که یک Controller دارید همراه با 15 عدد Action Method، یا یک Razor Page دارید که در PageModel آن چند Handler Method دارید، حالا نیاز به یک سرویسی دارید که در تمامی این Handler Methodها یا Action Methodها باید استفاده شود، مانند کلاس Context که برای EF Core است. حالا فرض کنید یکی از آن 15 کنترلرها نیاز به یک سرویس خاصی دارد، مثلا سرویس ارسال ایمیل، و در 14 تای دیگر این سرویس استفاده نمیشود، پس اینجا منطقی است که تزریق وابستگی به صورت مستقیم در خود Action Method انجام بگیرد. در مثال پایین میبینید که اینترفیس IEmailSender را در اکشن متد به صورت مستقیم تزریق کردهایم، بدون دخالت سازنده کلاس. البته این Abstraction باید یک کلاس پیاده سازی کننده داشته باشد و در DI Container پروژه به ثبت رسیده باشد.
مثال شماره 1:
public class AccountController : Controller { public IActionResult ConfirmEmail([FromServices] IEmailSender emailSender) { // emailSender.SendAsync(...); } }
مثال شماره 2:
public IActionResult About([FromServices] IDateTime dateTime) { ViewData["Message"] = $"Current server time: {dateTime.Now}"; return View(); }
مثال شماره 3:
[HttpGet] public ProductModel GetProduct([FromServices] IProductModelRequestService productModelRequest) { return productModelRequest.Value; }