درخواست های ارتباط
جستجو
لیست دوستان من
صندوق پیام
همه را دیدم
  • در حال دریافت لیست پیام ها
صندوق پیام
رویدادها
همه را دیدم
  • در حال دریافت لیست رویدادها
همه رویدادهای من
تخفیف های وب سایت
همه تخفیف ها

عضویت در

کانال تلگرام

توسینسو

اطلاعات مطلب
مدرس/نویسنده
حسین احمدی
امتیاز: 215942
رتبه:3
344
265
416
2833
حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ... پروفایل کاربر

آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و سوم :: آشنایی با مفاهیم Inversion of Control و Dependency Injection

تاریخ 43 ماه قبل
نظرات 4
بازدیدها 2734
در قسمت قبلی سری آموزشی با مفهوم interface ها آشنا شدیم. interface ها نقش بسیار موثری در روند نوشتن یک برنامه بازی می کنند و در صورتی که یک برنامه نویس با نحوه استفاده صحیح از interface ها آشنا باشه، توانایی ایجاد کدهایی ساختاریافته و قابل گستری و نگهداری رو داره. در این قسمت از سری آموزشی زبان برنامه نویسی سی شارپ و برنامه نویسی شئ گرا، با دو مفهوم بسیار مهم در برنامه نویسی آشنا خواهیم شد، IoC که مخفف Inversion of Control و DI که مخفف Dependency Injection هست.همه ما در طول زندگی با وسایل زیادی سر و کار داریم، از وسایل اولیه زندگی مانند ماشین، یخچال، تلویزیون و ... تا وسایل که هر کس بر اساس نیاز کاری خودش با اونها سر و کار داره، مانند کامپیوتر یا لپ تاپ و گوشی. برای مثال، گوشی هوشمند خود را فرض کنید، این گوشی از قطعات زیادی تشکیل شده، صفحه نمایش، پردازنده، حافظه رم، باتری و کلی قطعات دیگه. حالا اتفاقی پیش میاد و خدای نکرده گوشی شما از دستتون میافته و صفحه نمایش گوشیتون آسیب میبینه.

کاری که می کنید باید گوشی رو به یک نمایندگی برده و صفحه نمایش رو تغییر بدید. حالا فرض کنید که گوشی شما جوری طراحی شده باشه که با آسیب دیدن صفحه نمایش نیاز باشه تا یک گوشی جدید تهیه کنید!!!! یا برای کارتون یک لپ تاپ تهیه کردید. بعد از مدتی نیاز دارید تا حافظه رم لپ تاپ رو افزایش بدید. در این حالت شما لپ تاپ رو پیش نمایندگی یا یک کارشناس در این زمینه می برید و حافظه رم لپ تاپ شما افزایش داده میشه. حال فرض کنید که لپ تاپ شما همچین قابلیتی نداشته باشه و شما نیاز باشه برای تغییر یا ارتقا حافظه یک لپ تاپ جدید خریداری کنید! برای حل این مشکل لوازم الکتریکی از قطعات مختلفی تشکیل شدند که قابلیت تغییر یا تعویض دارند. به این قابلیت طراحی ماژولار گفته میشه. در پیاده سازی سیستم های نرم افزاری نیز شما نیز به عنوان برنامه نویس باید با همچین دیدی نسبت به پیاده سازی نرم افزار اقدام کنید. ما در اینجا در مورد تغییر یکی از قسمت های نرم افزار صحبت خواهیم کرد که ارتباط مستقیمی به interface ها و IoC و DI دارد.برای آشنایی بیشتر با این مفاهیم، با یک مثال جلو میرویم. فرض کنید سیستمی پیاده سازی کردید که اعضاء می توانند در این سامانه اقدام به ثبت نام کنند. برای عملیات های مرتبط با مدیریت اعضاء کلاسی با نام Members می نویسیم:

public class Members
{
    public void Register(string firstName, string lastName)
    {
        // add member to database            
    }
}

همانطور که مشاهده می کنید این کلاس یک متد با نام Register دارد که عملیات ثبت نام اعضاء را انجام می دهد (تنها متد تعریف شده و کدی برای ثبت نام نوشته نشده است). پس از مدتی، فردی که درخواست پیاده سازی نرم افزار را از شما داشته، می خواهد زمانی که یک عضو جدید به سامانه اضافه شد، یک ایمیل برای شخص ارسال شود. کد کلاس به صورت زیر تغییر می کند:

public class Members
{
    public void Register(string firstName, string lastName)
    {
        // add member to database
        // send email to name@host.com
    }
}

تا اینجا مشکلی نیست، بعد از مدتی مجدداً شخص ذکر شده از شما می خواهد به جای ارسال ایمیل، یک پیامک برای او ارسال شود. شما مجدداً باید کد داخل متد Register را تغییر داده و عملیات ارسال پیامک را اضافه کنید:

public class Members
{
    public void Register(string firstName, string lastName)
    {
        // add member to database
        // send sms to 0912*******
    }
}

با هر درخواست، ما دائماً در حال تغییر کدهای نوشته شده داخل کلاس Members هستیم. اگر کمی اصولی کار کنیم، کلاسی با نام SmsManager ایجاد می کنیم و از آن کلاس داخل کلاس Members استفاده می کنیم:

public class SmsManager
{
    public void Send(string message)
    {
        // send sms to 0912*******
    }
}

public class Members
{
    public void Register(string firstName, string lastName)
    {
        // add member to database
        var sms = new SmsManager();
        sms.Send("New user registered!");
    }
}

حالا فرض کنید که مجدد، شخص ذکر شده درخواست جایگزینی ارسال ایمیل به جای پیامک را به ما می دهد، ما کلاسی با نام EmailManager تعریف کرده و از آن استفاده می کنیم:

public class EmailManager
{
    public void Send(string message)
    {
        // send message to name@host.com
    }
}

public class SmsManager
{
    public void Send(string message)
    {
        // send sms to 0912*******
    }
}

public class Members
{
    public void Register(string firstName, string lastName)
    {
        // add member to database
        var email = new EmailManager();
        email.Send("New user registered!");
    }
}

با تعریف کلاس های EmailManager و SmsManager، حجم تغییرات کلاس Members خیلی کم شد. اما می توان این تغییرات را خیلی کمتر کرد. در اینجا می خواهیم یکی از کاربردهای بسیار مهم interface ها، یعنی IoC یا Inversion of Control را بررسی کنیم. در ابتدا ما یک interface با نام INotifySender به صورت زیر ایجاد می کنیم:

public interface INotifySender
{
    void Send(string message);
}

اگر دقت کنید، متد signature متد Send در کلاس های EmailManager و SmsManager مشترک است. پس این دو کلاس قابلیت پیاده سازی INotifySender را دارند. کلاس های ذکر شده را به صورت زیر تغییر می دهیم:

public class EmailManager : INotifySender
{
    public void Send(string message)
    {
        // send message to name@host.com
    }
}

public class SmsManager : INotifySender
{
    public void Send(string message)
    {
        // send sms to 0912*******
    }
}

در قدم بعدی باید کلاس Members را جوری تغییر دهیم تا وابستگی متد Register به یک کلاس خاص از بین برود، یعنی به کلاس EmailManager یا SmsManager وابسته نباشد. اینکار را می توان با استفاده از INotifySender انجام داد. کد کلاس Members را به صورت زیر تغییر می دهیم:

public class Members
{
    private readonly INotifySender sender;

    public Members()
    {
        sender = new EmailManager();
    }

    public void Register(string firstName, string lastName)
    {
        // add member to database
        sender.Send("New member registered!");
    }
}

تغییرات کد بالا را با هم بررسی می کنیم، فیلدی تعریف کردیم از نوع INotifySender که داخل متد Register از این فیلد برای ارسال پیام استفاده می کنیم. این فیلد از داخل سازنده کلاس Members مقدار دهی می شود. در کد بالا ما شئ ای از نوع EmailManager که INotifySender را پیاده سازی کرده است ایجاد کرده و داخل فیلد sender میریزیم. حال فرض کنید که بخواهیم عملیات را از ایمیل به پیامک تغییر دهیم، برای اینکار تنها سازنده را به صورت زیر تغییر می دهیم:

public class Members
{
    private readonly INotifySender sender;

    public Members()
    {
        sender = new SmsManager();
    }

    public void Register(string firstName, string lastName)
    {
        // add member to database
        sender.Send("New member registered!");
    }
}

به عملیات بالا، Inversion of Control گفته می شود. ما در حقیقت وابستگی متد Register را به یک کلاس خاص از بین بردیم. به این نوع پیاده سازی tightly coupled گفته می شود. اما باز یک مشکل وجود دارد، ما هنوز هم در حال تغییر کلاس Members هستیم. در قدم بعد باید وابستگی کلاس Members را به کلاس های EmailManager و SmsManager به طور کامل از بین ببریم. برای اینکار، ما به جای ساختن شئ داخل سازنده، آن را به عنوان یک پارامتر به سازنده کلاس Members ارسال می کنیم:

public class Members
{
    private readonly INotifySender sender;

    public Members(INotifySender sender)
    {
        this.sender = sender;
    }

    public void Register(string firstName, string lastName)
    {
        // add member to database
        sender.Send("New member registered!");
    }
}

نحوه استفاده از کلاس Members به صورت زیر است:

var members = new Members(new EmailManager());
members.Register("Hossein", "Ahmadi");

حال اگر بخواهیم نوع ارسال پیام را به پیامک تغییر دهیم تنها کافیست نوع شئ ارسالی به سازنده کلاس Members را تغییر دهیم:

var members = new Members(new SmsManager());
members.Register("Hossein", "Ahmadi");

به این تکنیک، DI یا Dependency Injection گفته می شود. ترکیب IoC و DI کمک زیادی به شما در نوشتن کدهایی می کنند که به راحتی قابلیت تغییر و به روز رسانی دارند. در این مقاله با یکی از کاربردهای بسیار مهم interface ها آشنا شدید. کتابخانه های آماده ای برای IoC و DI وجود دارند که به آنها IoC Container نیز گفته می شوند که روند DI رو برای شما به عنوان یک برنامه نویس بسیار راحت تر می کنند. در یک فیلم آموزشی در مورد IoC Container ها به تفصیل صحبت خواهیم کرد. در قسمت بعدی با مفهوم Type Casting و انواع Cast ها در زبان سی شارپ آشنا خواهیم شد. ITPRO باشید

نویسنده : حسین احمدی
منبع : جزیره برنامه نویسی وب سایت توسینسو
هرگونه نشر و کپی برداری بدون ذکر منبع و نام نویسنده دارای اشکال اخلاقی است
برچسب ها
ردیف عنوان
1 دوره آموزشی .NET Framework و زبان برنامه نویسی سی شارپ - مقدمه
2 آموزش سی شارپ - قسمت اول :: معرفی و بررسی ابزارهای مورد نیاز دوره
3 آموزش زبان سی شارپ - قسمت دوم :: آشنایی با .NET Framework و ساختار آن (بخش اول)
4 آموزش زبان سی شارپ - قسمت دوم :: آشنایی با .NET Framework و ساختار آن (بخش دوم)
5 آموزش زبان سی شارپ - قسمت سوم :: آشنایی اولیه با محیط Visual Studio و نوشتن اولین برنامه
6 آموزش زبان سی شارپ - قسمت چهارم :: آشنایی با ساختار برنامه ها و کامپایلر زبان سی شارپ
7 آموزش زبان سی شارپ - قسمت پنجم :: آشنایی با دستورات کنسول و متغیرها
8 آموزش زبان سی شارپ - قسمت ششم :: نوع های داده اولیه
9 آموزش زبان سی شارپ - قسمت هفتم :: آشنایی با عملگرهای زبان سی شارپ
10 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش اول)
11 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش دوم)
12 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش سوم)
13 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش چهارم)
14 آموزش زبان سی شارپ - قسمت نهم :: آشنایی با آرایه ها و دستور foreach
15 آموزش زبان سی شارپ - قسمت دهم :: آشنایی با متدها در زبان سی شارپ (بخش اول)
16 آموزش زبان سی شارپ - قسمت دهم :: آشنایی با متدها در زبان سی شارپ (بخش دوم)
17 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت یازدهم :: مقدمه ای بر برنامه نویسی شئ گرا
18 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت دوازدهم :: آشنایی با کلاس، اشیاء و فضاهای نام
19 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت سیزدهم :: آشنایی با فیلدها و رفتارها
20 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت چهاردهم :: آشنایی با Property ها
21 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت پانزدهم :: آشنایی با سازنده ها و روش های ایجاد اشیاء
22 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت شانزدهم :: وراثت یا Inheritance
23 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت هفدهم :: آشنایی با مفهوم Polymorphism
24 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت هجدهم:: کلاس های abstract و sealed
25 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت نوزدهم :: سازنده ها در وراثت، کلمه کلیدی protected و فیلدهای readonly
26 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیستم :: کلاس های static و partial و Extension Method ها
27 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و یکم :: Reference Types و Value Types
28 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و دوم :: آشنایی با کاربرد interface ها
29 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و سوم :: آشنایی با مفاهیم Inversion of Control و Dependency Injection
30 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و چهارم :: آشنایی با مفهوم Type Casting و انواع Cast ها
31 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و پنجم :: آشنایی با operator overloading و تعریف cast ها
32 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و ششم :: مفاهیم boxing و unboxing
33 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و هفتم :: قابلیت Generics
34 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و هشتم :: نکات تکمیلی Generic ها، کلاس List و کلاس Dictionary
35 آموزش زبان سی شارپ -قسمت بیست و نهم (پایانی): استثناء ها (Exceptions) و مدیریت خطاها در سی شارپ
دوره مجموعه کل دوره
مطالب مرتبط

در حال دریافت اطلاعات

نظرات
  • سلام
    جناب مهندس اگر مشخص بکنید که آموزش ها رو در یک بازه ی زمانی مشخص منتشر کنید
    بسیار عالی خواهد شد.
    ممنون
    --موفق باشید
  • جناب احمدی یه سوال در مورد فریم ورک هایی هست که برای ِDI توسعه دادن
    ببینید مثلا یکی از انواع همین DI ها واسه سازنده ها هست ... در واقع این جور که متوجه شدم بعد از یه مدت استفاده از سازنده ها با امضاهای متوافت و با ورودی های متفاوت ازاینترفیس های متفاوت تو برنامه زیاد میشه اگه اشتباه نکنم از Ninject برای این استفاده میشه که بیاد Di رو پیاده سازی کنه ... می خواستم ببینم این طور که بنده متوجه شدم درست هست که در واقع برای کنترل کردن این سازنده ها که بشه نظارت بهتری روش داشت در واقع این فریم ورک ها اومدن ساخته شدن یا این که از این مفاهیم به درستی تو پروزه ها استفاده نمیشده و اومدن در واقع یه نوع استاندارد سازی کردن ؟

    با تشکر از شما
  • سلام چرا اجرای این روش چیزی رو در خروجی نشون نمی ده؟
    DI

  • عالی عالی عالییییی ...... با اینکه توو متن توضیح میدین ولی آموزشون کاملا شیواست. آدم کیف میکنه....
    بی نهایت سپاسگزارم

برای ارسال نظر ابتدا به سایت وارد شوید