ورود ثبت نام

ورود به حساب کاربری

نام کاربری *
رمز ورود *

ایجاد حساب کاربری

گزینه های * دار الزامی می باشند.
نام *
نام کاربری *
رمز ورود *
تائیدیه رمز ورود *
نشانی پست الکترونیک *
تائیدیه پست الکترونیک *

در ابتدا این سوال پیش می آید که تزریق وابستگی چیست و چه کاربردی دارد؟ در جواب می توان اینگونه گفت که تزریق وابستگی تکنیکی است که با کمک آن به راحتی میتوان اجزاء مستقل از هم ساخت به گونه ای که اگر هر کلاس کلاس دیگری را در خود به کار برد هیچ وابستگیی به آن و نحوه ایجاد آن کلاس نخواهد داشت. به زبان ساده تر در این تکنیک شما به جای اینکه یک کلاس را در کلاس دیگر مورد استفاده قرار دهید به جای اینکه یک نمونه از آن را آنرا در کلاس مربوطه بسازید، تزریق کرده و از آن استفاده می نمایید.

در این الگو شما با استفاده از تعریف یک اینترفیس برای کلاس مربوطه و ارث بری کلاس از آن اینترفیس، وابستگی های موجود بین این کلاس را با کلاسی که قرار است از آن استفاده کند را از بین می برید. کلاسهای طراحی شده با این الگو دارای کمترین وابستگی به همدیگر هستند که به اصطلاح به آنها (Loosely Coupled Components) اطلاق می شود.

تزریق وابستگی برای برطرف کردن دو معضل موجود در طراحی شیءگرا  یعنی ماژولهای نرم افزاری مرتبط (coupling software module)و وابستگی ارتباط  (coupling dependencies) طراحی گردید  که در آن ازا اصل طراحی وارونگی کنترل  (inversion of control)  و الگوی طراحی وارونگی وابستگی (dependency inversion) برای رفع این دو مشکل استفاده شده است و در حقیقت تزریق وابستگی یکی از تکنیکهای موجود در پیاده سازی واصل وارونگی کنترل می باشد. DI به ما این امکان را می دهد که اشیاء وابسته به یک کلاس را در خارج از آن کلاس تعریف نموده و در آن از آنها استفاده نماییم بدون اینکه کلاس را وابسته به آنها نماییم. شکل زیر ارتباط موارد بالا را نشان می دهد:

تزریق وابستگی

الگوی تزریق وابستگی شامل سه نوع کلاس می شود:

  • Client Class: کلاسی که وابسته به کلاس سرویس است.
  • Service Class: کلاسی که به کلاس کلاینت سرویس می دهد.
  • Injector Class: کلاسی که کلاس سرویس را به کلاس کلاینت تزریق می کند.

شکل زیر ارتباط این کلاسها را نشان می دهد:

تزریق وابستگی

انواع تزریق وابستگی:

تزریق وابستگی از سه روش زیر انجام می شود:

  • تزریق سازنده (Constructor Injection): در این روش کلاس سرویس از طرق تزریق به سازنده کلاس کلاینت به آن داده می شود.
  • تزریق ویژگی (Property Injection): در این روش از طریق یک فیلد عمومی (public property) کلاس کلاینت تزریق صورت می گیرد.
  • تزریق متد (Method Injection): در این روش کلاس کلاینت یک اینترفیس حاوی متدهایی برای تزریق وابستگی را پیاده سازی می نماید.

اجازه بدهید هر یک از موارد بالا را به اختصار شرح دهیم:

Constructor Injection:

همانطور که گفته شد در این روش تزریق بوسیله سازنده کلاس صورت می گیرد. به مثال زیر توجه کنید:

public class CustomerBusinessLogic
{
    ICustomerDataAccess _dataAccess;

    public CustomerBusinessLogic(ICustomerDataAccess custDataAccess)
    {
        _dataAccess = custDataAccess;
    }

    public CustomerBusinessLogic()
    {
        _dataAccess = new CustomerDataAccess();
    }

    public string ProcessCustomerData(int id)
    {
        return _dataAccess.GetCustomerName(id);
    }
}

public interface ICustomerDataAccess
{
    string GetCustomerData(int id);
}

public class CustomerDataAccess: ICustomerDataAccess
{
    public CustomerDataAccess()
    {
    }

    public string GetCustomerName(int id) 
    {
        //get the customer name from the db in real application        
        return "Dummy Customer Name"; 
    }
}

در این مثال CustomerBusinessLogic دارای سازنده ای با یک پارامتر ورودی از نوع ICustomerDataAccess می باشد.

 

Property Injection:

به مثال زیر توجه نمایید:

public class CustomerBusinessLogic
{
    public CustomerBusinessLogic()
    {
    }

    public string GetCustomerName(int id)
    {
        return DataAccess.GetCustomerName(id);
    }

    public ICustomerDataAccess DataAccess { get; set; }
}

public class CustomerService
{
    CustomerBusinessLogic _customerBL;

    public CustomerService()
    {
        _customerBL = new CustomerBusinessLogic();
        _customerBL.DataAccess = new CustomerDataAccess();
    }

    public string GetCustomerName(int id) {
        return _customerBL.GetCustomerName(id);
    }
}

همانطور که در بالا مشاهده می نمایید، کلاس CustomerBusinessLogic دارای یک ویژگی عمومی با نام DataAccess است که به آن یک نمونه از اینترفیس ICustomerDataAccess انتساب داده شده است.

 

Method Injection:

 در این روش کلاسهای وابسته از طریق متدها قابل دسترسی هستند. این متدها می توانند متدهای کلاس و یا متدهای اینترفیس باشند. مثال زیر را در نظر بگیرید:

interface IDataAccessDependency
{
    void SetDependency(ICustomerDataAccess customerDataAccess);
}

public class CustomerBusinessLogic : IDataAccessDependency
{
    ICustomerDataAccess _dataAccess;

    public CustomerBusinessLogic()
    {
    }

    public string GetCustomerName(int id)
    {
        return _dataAccess.GetCustomerName(id);
    }
        
    public void SetDependency(ICustomerDataAccess customerDataAccess)
    {
        _dataAccess = customerDataAccess;
    }
}

public class CustomerService
{
    CustomerBusinessLogic _customerBL;

    public CustomerService()
    {
        _customerBL = new CustomerBusinessLogic();
        ((IDataAccessDependency)_customerBL).SetDependency(new CustomerDataAccess());
    }

    public string GetCustomerName(int id) {
        return _customerBL.GetCustomerName(id);
    }
}

در مثال بالا کلاس CustomerBusinessLogic اینترفیس IDataAccessDependency که حاوی متد SetDependency است را پیاده سازی می نماید. بنابراین تزریق کلاس با کمک متد انجام می شود.

تزریق وابستگی در ASP.net core

در .net core یک کلاس باید انتزاعی از یک اینترفیس باشد. به مثال زیر دقت کنید:

public interface IDataService
{
    IList<DataClass> GetAll();
}

public class DataService : IDataService
{
    public IList<DataClass> GetAll()
    {
        //Get data...
        return data;
    }
}

در مرحله بعد باید این اینترفیس در فایل پیکربندی پروژه به عنوان یک سرویس تزریق وابستگی رجیستر شود. قبل از اینکار ما باید با چرخه زندگی سرویس آشنا شویم.

سه گزینه برای چرخه زندگی سرویس در ASP.Net Core تعریف شده است

  • Singleton: بدان معنی است که تنها یک نمونه از اینترفیس می تواند در برنامه ساخته شود. این یک نمونه بین همه کلاسها به اشتراک گذاشته می شود و همیشه و در طول عمر برنامه مورد استفاده قرار می گیرد.
  • Scoped: در هی scope یک نمونه از اینترفیس ساخته می شود. یک scope روی هر درخواست رسیده به برنامه ایجاد می شود و بنابراین هر سرویس رجیستر شده با این چرخه زندگی به ازاء هر درخواست ایجاد خواخد شد.
  • Transient: کامپوننتها و سرویس های دارای این چرخه زندگی به ازاء هر درخواست ایجاد می شوند و هرگز به اشتراک گذاشته نمی شوند.

همانطور که گفته شد در گام بعدی اینترفیس باید رجیستر شود. برای اینکار در فایل پیکربندی startup.cs و در متد ConfigureServices دستور زیر را درج می کنیم:

services.AddTransient <IDataService, DataService>();

و در نهایت در کنترلر مربوطه برای استفاده از کلاس DataService  مانند زیر عمل می نماییم:

public class HomeController : Controller
{
    private readonly IDataService _dataService;

    public HomeController(IDataService dataService)
    {
        _dataService = dataService;
    }

}

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

نوشتن دیدگاه


تصویر امنیتی
تصویر امنیتی جدید