بررسی قابلیت Dependency Injection در ASP.NET Core

بررسی قابلیت Dependency Injection در ASP.NET Core

در این پست از وبسایت پرووید، در رابطه با بررسی قابلیت Dependency Injection در ASP.NET Core صحبت خواهیم کرد. به ادامه ی مطلب بروید.

در این قسمت از سری آموزش کامل و متنی ASP.NET Core از وب سایت پرووید در رابطه با Dependency Injection در ASP.NET Core صحبت خواهیم کرد. در همین ابتدای کار به شما توصیه می کنیم که اگر در رابطه با Dependency Injection به دنبال اطلاعات بیشتری هستید از سری کامل و متنی آموزش اصل Inversion of Control در برنامه نویسی از وب سایت پرووید استفاده کنید. همانطور که ممکن است بدانید ASP.NET Core بصورت درونی از Dependency Injection پشتیبانی می کند و بسادگی Object های مربوط به Dependency ها را به درون توابع سازنده و یا Constructor ها و یا حتی متدها Inject می کند. اینکار با استفاده از یک IoC Container که بصورت Built-in و یا درونی در ASP.NET Core تعبیه شده است انجام می شود.

بررسی IoC Container ساخته شده در ASP.NET Core

همانطور که گفتیم در ASP.NET Core یک IoC Container بصورت درونی و یا Built-in تعبیه شده است. البته این را هم بدانید که این IoC Container قابلیت های محدودی دارد. اگر بدنبال قابلیتهای بیشتری از قبیل Auto-registration و Scanning و Interceptor ها و Decorator ها هستید باید بجای استفاده کردن از IoC Container مربوط به ASP.NET Core از یک IoC Container دیگر استفاده کنید.

در IoC Container مربوط به ASP.NET Core اینترفیس IServiceProvider پیاده سازی شده است و عملیات تزریق با استفاده از تابع سازنده انجام می شود. در رابطه با روشهای مختلف تزریق وابستگی ها، در آموزش ویدئویی Dependency Injection در برنامه نویسی شی گرا از وب سایت پرووید بطور مفصل صحبت کرده ایم.

علاوه بر این، کلاسها و یا Dependency ها در IoC Container مربوط به ASP.NET Core با نام Service تعریف می شوند. در ASP.NET Core بطور کلی دو نوع Service وجود دارد.

بررسی Framework Service ها

این دسته از Service ها شامل Service های می شوند که بخشی از فریم ورک ASP.NET Core هستند. برای مثال IApplicationBuilder و IHostingEnvironment و ILoggerFactory سه نمونه از Framework Service ها می باشند.

بررسی Application Service ها

این نوع از Service ها در واقع کلاسها و یا Custom Type هایی هستند که خود برنامه نویس آنها را ایجاد کرده و به عنوان Dependency و یا Service در برنامه از آنها استفاده می کند.

به منظور اینکه بتوانیم از IoC Container بخواهیم که بصورت خودکار Application Service ها را به درون توابع سازنده مربوطه تزریق کند ابتدا باید آنها را Register کنیم.

بررسی روند Register کردن Application Service ها

در این قسمت قصد داریم که نحوۀ Register کردن و سپس تزریق کردن یک Implementation و یا پیاده سازی از اینترفیس ILog را در ASP.NET Core بررسی کنیم. کدی که در زیر مشاهده می کنید اینترفیس ILog و پس از آن یک پیاده سازی از آن را نشان می دهد.

public interface ILog
{
    void info(string str);
}

class MyConsoleLogger : ILog
{
    public void info(string str)
    {
        Console.WriteLine(str);
    }
}

در ASP.NET Core امکان Register کردن Application Service ها با IoC Container مربوطه وجود دارد. به منظور انجام اینکار از متد ConfigureServices از کلاس Startup استفاده می کنیم. متد ConfigureServices دارای یک پارامتر از نوع IServiceCollection می باشد که به منظور Register کردن Application Service ها استفاده می شود. در ادامه اقدام به Register کردن ILogg در IoC Container مربوط به ASP.NET Core می کنیم. این موضوع در متد ConfigureServices() از کلاس Startup انجام می شود. کد زیر این موضوع را نشان می دهد.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Add(new ServiceDescriptor(typeof(ILog), new MyConsoleLogger()));        
    }

    // other code removed for clarity.. 
}

همانطور که در کد بالا نیز مشاهده می کنید از متد Add() از اینترفیس IServiceCollection به منظور Register کردن یک Service استفاده کرده ایم. علاوه بر این از ServiceDescriptor به منظور مشخص کردن نوع سرویس مورد نظر و همچنین پیاده سازی آن استفاده کرده ایم. در این دستور مشخص کرده ایم که ILog نوع سرویس و کلاس MyConsoleLogg یک پیاده سازی از آن است. این موضوع باعث Register شدن سرویس ILog بصورت Singleton می شود. با انجام این کار هر زمان که یک کلاس و یا یک متد به ILog به عنوان یک Dependency نیاز داشته باشد IoC Container یک Object از MyConsoleLogger را ایجاد کرده و به درون آن تابع سازنده یا آن متد تزریق می کند. دقت کنید که بطور پیش فرض Dependency ها در IoC Container مربوط به ASP.NET Core بصورت Singleton رجیستر می شود.

علاوه بر روشی که برای Register کردن Application Service ها در IoC Container مشاهده کردید، Extension Method های دیگری نیز برای انجام عملیات Register کردن بصورت کوتاه و سریع می باشند که در ادامه در رابطه با آنها صحبت خواهیم کرد.

بررسی Service Lifetime در IoC Container

کلمه Lifetime در زبان انگلیسی به معنی طول عمر می باشد. IoC Container مربوط به ASP.NET Core طول عمر سرویس های Register شده را بر اساس Lifetime مشخص شده مدیریت می کند. پس از پایان یافتن طول عمر Service ها، آنها را از حافظه خارج کرده و یا اصطلاحاً Dispose می کند. بطور کلی سه طول عمر و یا Lifetime در IoC Container مربوط به ASP.NET Core وجود دارند.

طول عمر Singleton

با استفاده از این طول عمر IoC Container یک Object تک از سرویس مورد نظر را ایجاد کرده و در سر تا سر اپلیکیشن بصورت اشتراکی از آن استفاده می کند. برای درک هرچه بهتر طول عمر Singletone بهتر است از بسته ی آموزش ویدئویی Design Pattern ها در سی شارپ استفاده کنید و به بررسی الگوی طراحی Singleton بپردازید.

طول عمر Transient

با استفاده کردن از این طول عمر IoC Container یک Object جدید از سرویس مورد نظر را هر زمان که به آن نیاز داشته باشید ایجاد می کند. به عبارت دیگر به ازای هر درخواست از سرویس مورد نظر، یک Object جدید ایجاد می شود. واژه ی Transient در زبان انگلیسی به معنای نا پایدار و یا نامانا است که معنی این طول عمر را واضح تر می کند.

طول عمر Scoped

با استفاده کردن از این طول عمر IoC Container یک Object از سرویس مورد نظر را به ازای هر درخواست و یا Request ایجاد کرده و در طول آن Request بصورت اشتراکی مورد استفاده قرار می دهد. کدی که در قسمت زیر مشاهده می کنید نحوۀ Register کردن سرویس های مختلف با Lifetime های مختلف را نشان می دهد.

public void ConfigureServices(IServiceCollection services)
{
    services.Add(new ServiceDescriptor(typeof(ILog), new MyConsoleLogger()));    // singleton
    
    services.Add(new ServiceDescriptor(typeof(ILog), typeof(MyConsoleLogger), ServiceLifetime.Transient)); // Transient
    
    services.Add(new ServiceDescriptor(typeof(ILog), typeof(MyConsoleLogger), ServiceLifetime.Scoped));    // Scoped
}

بررسی Extension Method های موجود برای انجام عملیات Register کردن

فریم ورک ASP.NET Core دارای Extension Method های مختلفی برای Register کردن سرویس ها با Lifetime های مختلف است. اگر مفهوم Extension Method را نمی دانید از آموزش کامل توسعه نرم افزار با سی شارپ استفاده کنید. برای مثال می توانید از متدهای AddSingleton() و AddTransient() و AddScoped() به منظور Register کردن یک سرویس با طول عمر Singleton و Transient و Scoped استفاده کنید. کدی که در قسمت زیر مشاهده می کنید نحوه ی استفاده کردن از این Extension Method ها را نشان می دهد.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ILog, MyConsoleLogger>();
    services.AddSingleton(typeof(ILog), typeof(MyConsoleLogger));

    services.AddTransient<ILog, MyConsoleLogger>();
    services.AddTransient(typeof(ILog), typeof(MyConsoleLogger));

    services.AddScoped<ILog, MyConsoleLogger>();
    services.AddScoped(typeof(ILog), typeof(MyConsoleLogger));
}

بررسی کردن Constructor Injection

قبل از اینکه این بحث را باز کنیم، توصیه می کنیم حتماً آموزش تکنیک تزریق وابستگی (Dependency Injection) در برنامه نویسی شی گرا که در آن در رابطه با Constructor Injection و Property Injection و همچنین Interface Injection صحبت کرده ایم را مطالعه کنید.

پس از Register کردن یک سرویس در IoC Container عملیات تزریق وابستگی ها بصورت Constructor Injection انجام می شود. این موضوع زمانی رخ می دهد که Dependency مربوطه در تابع سازنده یک کلاس بعنوان پارامتر تعریف شده باشد.

بسته ی آموزش ویدئویی ساخت یک Enterprise Application با ASP.NET Core MVC

از شما دعوت می کنیم که از بسته ی آموزش ویدئویی ساخت یک Enterprise Application با ASP.NET Core MVC دیدن کنید.

برای مثال اگر سرویس ILog که در قسمتهای قبل آن را Register کردیم به عنوان یک Dependency در تابع سازنده ی یک Controller تعریف شده باشد، عملیات Constructor Injection انجام می شود. کد زیر نیز این موضوع را نشان می دهد.

public class HomeController : Controller
{
    ILog _log;

    public HomeController(ILog log)
    {
        _log = log;
    }
    public IActionResult Index()
    {
        _log.info("Executing /home/index");

        return View();
    }
}

کدی که در قسمت بالا مشاهده می کنید باعث می شود که IoC Container یک Object از نوع MyConsoleLogger را به درون Constructor مربوط به HomeController تزریق کند. هیچ کار دیگری نیاز نیست انجام بدهید. در واقع IoC Container بصورت خودکار یک Object جدید از ILog را ایجاد کرده و سپس آن را از حافظه خارج و یا Dispose می کند. اینکه چه کلاسی از اینترفیس ILog ایجاد بشود بسته به فرایند Register کردنی دارد که در قسمت های قبلی به آن پرداختیم.

بررسی Action Method Injection

گاهی اوقات نیاز است که یک Dependency را فقط در درونِ یک متدِ تک از یک Controller داشته باشیم. به منظور انجام اینکار از یک Attribute با نام FromService استفاده می کنیم. این Attribute قبل از پارامتر تعریف شده برای متد مورد نظر تنظیم می شود. این موضوع نیز در کد زیر نشان داده شده است.

using Microsoft.AspNetCore.Mvc;

public class HomeController : Controller
{
    public HomeController()
    {
    }

    public IActionResult Index([FromServices] ILog log)
    {
        log.info("Index method executing");

        return View();
    }
}

بررسی Property Injection

در IoC Container مربوط به ASP.NET Core عملیات Property Injection پشتیبانی نمی شود. اگر بطور خاص به Property Injection نیاز دارید باید از یک IoC Container دیگر استفاده کنید.

بدست آوردن سرویسها بصورت دستی

اگر نیازی ندارید که بصورت خودکار عملیات تزریق وابستگی ها در درون Constructor مربوط به یک Controller و یا یک Action Method انجام بشود، می توانید سرویسها را بصورت دستی نیز بدست بیاورید. این موضوع با استفاده از یک Property به نام RequestServices از کلاس HTTPContext انجام می شود.

بسته ی آموزش ویدئویی شروع به کار با ASP.NET Core و SignalR

از شما دعوت می کنیم که از بسته ی آموزش ویدئویی شروع به کار با ASP.NET Core و SignalR دیدن کنید.

کد زیر این موضوع را نشان می دهد.

public class HomeController : Controller
{
    public HomeController()
    {
    }
    public IActionResult Index()
    {
        var services = this.HttpContext.RequestServices;
        var log = (ILog)services.GetService(typeof(ILog));
            
        log.info("Index method executing");
    
        return View();
    }
}

دقت کنید که این روش خیلی توصیه نمی شود. توصیه ما این است که از Constructor Injection بجای استفاده کردن از RequestServices استفاده کنید. در قسمت بعدی از این آموزش در رابطه با Middleware و یا مفهوم میان افزار در ASP.NET Core صحبت خواهیم کرد.

امیدواریم که این آموزش از وبسایت پرووید نیز مورد توجه تمامی دوستان عزیز قرار گرفته باشد. از شما دعوت می‌کنیم که از دیگر آموزش های ما در رابطه با فریم ورک ASP.NET Core استفاده کنید. لیست کامل این آموزش ها را می توانید در پست مربوط به آموزش کامل توسعه وب اپلیکیشن با ASP.NET Core مشاهده کنید.

مرتضی گیتی
بدون نظر

ارسال نظر

نظر
نام
ایمیل
وب سایت