dependency injection در سی شارپ
1399-05-21

داستان حیرت آور dependency injection در سی شارپ

تزریق وابستگی در سی شارپ

در این مقاله می خواهیم درباره dependency injection در سی شارپ بحث کنیم. اما قبل از آن باید با دو مفهوم آشنا باشید: 

  1. اصل وارونگی وابستگی (Dependency Inversion Principle) یا به اختصار DIP
  2. وارونگی کنترل (Inversion of Controls) یا به اختصار IoC

Dependency Inversion Principle:

اصول شی گرایی

یکی از اصول شی گرایی است که توسط آقای رابرت مارتین معروف به عمو باب ابداع شد. اصل وارونگی وابستگی در واقع یک اصل طراحی نرم افزار است که به ما در تولید یک نرم افزار با استحکام ارتباطی کم (Loosely Coupled) کمک می کند. به بیان ساده تر یعنی: ماژول های سطح بالا نباید به ماژول های سطح پایین وابسته باشند، بلکه باید هر دو به یک رابط وابسته شوند. انتزاع‌ (abstraction) نیز نباید به جزئیات وابسته باشد بلکه جزئیات باید به انتزاع وابسته باشند. (منظور از انتزاع دید کلی نسبت به یک شی است مثلا وقتی ما می‌گوییم میز ،چیزی که در ذهن ما نقش می‌بندد یک شکل کلی است ولی وقتی می‌گوییم میز ناهارخوری دقیقا مشخص می‌کنیم که چه نوع میزی است.)

Inversion of Control:

همانطور که ملاحظه کردید اصل وارونگی وابستگی به ما می‌گوید که وابستگی دو ماژول باید چگونه باشد. برای اجرای این موضوع باید از IoC یا از وارونگی کنترل استفاده کنیم. IoC روشی کاملا کاربردی‌ است که توسط آن ماژول‌های سطح بالا را به جای وابسته کردن به ماژول‌های سطح پایین، به انتزاع‌ها (abstractions) متصل می‌کند.

بگذارید با بیان یه مثال این مطلب را برای شما بیان کنیم. فرض کنید که سوار بر خودرو به سمت محل کار خود در حال رانندگی هستید، این یعنی شما در حال کنترل خودروی خود هستید. حالا اصل IoC چی میگه؟ این اصل،  وارونه کردن کنترل را پیشنهاد میدهد یعنی شما به جای آنکه خودتان رانندگی کنید، یک تاکسی بگیرید و بگذارید فرد دیگری رانندگی کند. در این صورت  کنترل از شما به راننده ی تاکسی وارونه می شود و شما دیگر مجبور نیستید خودتان رانندگی کنید و برای آنکه بتوانید بر روی کار اصلی خود تمرکز کنید، این کار را به راننده ی تاکسی محول می کنید.

آموزش سی شارپ

تعریف dependency injection  در سی شارپ:


تزریق وابستگی یا Dependency Injection یک پترن و الگوی طراحی است که هدف اصلی آن حذف وابستگی‌ های موجود بین دو کلاس با استفاده از یک رابط (Interface) است.

تعریف dependency injectionدر تزریق وابستگی ها دو اصطلاح داریم.

  • loosely coupled: وجود کمترین وابستگی بین دو کلاس
  • tight coupled: وجود بیشترین وابستگی بین دو کلاس 

بنابراین باید برنامه و نرم‌افزار خود را طوری طراحی کنیم که تا حد ممکن استحکام بین دو کلاس ضعیف باشد. چون زمانی که دو کلاس وابستگی بسیار دارند یا به اصطلاح در هم چفت شده‌اند، انعطاف‌پذیری نرم‌افزار را به شدت پایین می‌آورند.

مثال:

حالا می خواهیم با یک مثال جذاب داستان تزریق وابستگی در سی شارپ را برایتان بگوییم. فرض کنید می خواهیم یک بازی به نام نینجا بنویسیم که در آن جنگجوهای شجاع، برای به دست آوردن شرافتشان، با دشمنان خود میجنگند اما قبل از هر چیزی باید برای جنگجوهای خود یک سلاح مناسب تهیه کنیم. یک شمشیر که نام آن را Sword می گذاریم و دست به کار می شویم: این کلاس یک متد hit (ضربه زدن) دارد و هروقت آنرا فراخوانی کنیم، ضربه زده خواهد شد و target یا همان هدفمان نصف میشود! خوب، این از سلاح.

class Sword 
{
    public void Hit(string target)
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}


حالا باید سامورایی بسازیم برای حمله به دشمن.  کلاس سامورایی ما باید یک متد حمله یا Attack داشته باشد که وقتی آنرا فراخوانی می کنیم سامورایی با شمشیرش، هدف را نصف کند.

class Samurai
{
    readonly Sword sword;
    public Samurai() 
    {
        this.sword = new Sword();
    }

    public void Attack(string target)
    {
        this.sword.Hit(target);
    }
}


 حالا کافی است که سامورایی را ساخته و بجنگیم!

class Program
{
    public static void Main() 
    {
        var warrior = new Samurai();
        warrior.Attack("the evildoers");
    }
}

در این کد، ما با evildoers میجنگیم و او را با شمشیر نصف میکنیم. اما فرض کنید بخواهیم سامورایی ما با سلاح دیگری به غیر از شمشیر بجنگد! مثلا با شوریکن تیغه برنده شبیه ستاره. در این صورت باید کلاس سامورایی را کلا تغییر دهیم چون در کلاس سامورایی فقط از کلاس شمشیر استفاده کرده ایم. پس هر بار که نینجای ما بخواهد با یک سلاح جدید بجنگد، باید کلاس سامورایی را تغییر دهیم. به این ترتیب Tightly Coupled رخ می دهد یعنی وابستگی کلاس سامورایی به کلاس شمشیر.

طبیعتا ما این نوع وابستگی ها را دوست نداریم. چون مجبورمان میکند کدمان را تغییر دهیم. برای از بین بردن این وابستگی ها، از interfaceها استفاده میکنیم. بیایید یک interface به نام سلاح(weapon) بسازیم:

interface IWeapon
{
    void Hit(string target);
}


حالا کلاس شمشیر، را به این interface متصل میکنیم یا اصطلاحا آنرا Implement میکنیم:

class Sword : IWeapon
{
    public void Hit(string target) 
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}


حالا سامورایی را طوری تغییر میدهیم که به جای یک شمشیر، از یک سلاح استفاده کند:

class Samurai
{
    readonly IWeapon weapon;
    public Samurai() 
    {
        this.weapon = new Sword();
    }

    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}


حالا سامورایی ما میتواند از سلاح های مختلفی استفاده کند. فقط یک جای کار میلنگد. ما هنوز هم از شمشیر، در کلاس سامورایی استفاده می کنیم:
 

 this.weapon = new Sword();


پس باید کلاس سامورایی را یک کمی بهتر کنیم. کافی است که سلاح مورد نظر را از طریق constructor به سامورایی بدهیم:

class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon) 
    {
        this.weapon = weapon;
    }

    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}


حالا کافی است که سلاح مورد نظرمان را از طریق constructor به سامورایی تزریق کنیم. قبل از این، اجازه بدهید یک سلاح جدید به غیر از شمشیر هم بسازیم:

class Shuriken : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Pierced {0}'s armor", target);
    }
}


وقتشه تا یک ارتش سامورایی با سلاح های مختلف بسازیم و به evildoers حمله کنیم. حاضرید؟

class Program
{
    public static void Main() 
    {
        var warrior1 = new Samurai(new Shuriken());
        var warrior2 = new Samurai(new Sword());
        warrior1.Attack("the evildoers");
        warrior2.Attack("the evildoers");
    }
}

 

کلام آخر:

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

مقالات مرتبط

تفاوت dp و px در برنامه نویسی اندروید

واحد های اندازه گیری اندروید
زهرا چگینی
10

به نظر شما تفاوت dp و px در برنامه نویسی اندروید، این دو واحد اندازه گیری چیست؟ پس ما را همراهی کنید.

delegate چیست؟

Delegate ها چرا به زبان سی شارپ اضافه شدند؟
مرضیه فتاحی
15

delegate چیست؟ چه کاربردی دارد؟ چگونه و در چه موقعیت هایی باید ازآنها استفاده کرد؟ با ما همراه شوید تا تمامی این سوال ها دریابید.

اکشن (Action) در سی شارپ، راهی برای خواناتر شدن کدها

موارد استفاده ی Action در سی شارپ
زهرا چگینی
10

Action در سی شارپ از پایه و اساس Delegate ها استفاده میکند، درحقیقت همان Delegate های هستند که کار را برای ما راحت تر میکنند.

Extension method درسی شارپ، راهی برای کارایی بالا در کدها

اکستنشن (extension) درسی شارپ
مرضیه فتاحی
10

هدف ما دانستن نکات مهمextension method در سی شارپ، نحوه استفاده و همچنین کاربرد آن در کدنویسی است. پس با ما همراه شوید.

لیست کامل تگ های html که هیچ کس به شما نخواهد گفت

آشنایی با تگ های html
زهرا چگینی
15

تگ ها در html نقش مهمی دارند زیرا تمامی کارهای html با تگ انجام می‌شود. به همین دلیل ما یک لیست کامل از تگ‌های html برای شما آماده کرده‌ایم تا از آن استفاده کنید.

ویژگی های جدید asp.net core که حیرت برنامه نویسان را برانگیخت

معرفی ویژگی های جدید asp.net core از مایکروسافت
مرضیه فتاحی
10

ویژگی های جدید asp.net core چیست؟ مایکروسافت در این نسخه چه امکاناتی را برای برنامه نویسانش قرار داده است. اگر شما هم خواهان دانستن این مطالب هستید، ما را همراهی کنید.