View Full Version : سوال: استفاده از اینترفیس IRepository در MVC
OmMiD_MtWo
سه شنبه 04 خرداد 1395, 16:26 عصر
با سلام
من قبلا هنگام استفاده از MVC تمامی مدلها و متدهای مربوط به کار با پایگاه داده رو در داخل پروژه استفاده میکردم تا اینکه با مفهوم Repository Pattern آشنا شدم و تصمیم گرفتم تا مدل ها و متدهای مربوط به کار با پایگاه داده را در Class Library جداگانه به Solution اضافه کنم و از این طریق با کنترلهای MVC کار کنم. به همین دلیل از یک اینترفیس به نام IRepository استفاده کردم که عملیات CRUD رو تعریف میکنه و در ادامه Repositoryهای مربوط به مدلها رو از این اینترفیس ارث بری کردم و افزونه ی Unity.MVC رو هم برای انجام عملیات Dependency Injectionبه پروژه اضافه کردم؛ هر چی مطلب راجب الگوی Repository و تزریق وابستگی مطالعه کردم چیزی دستگیرم نشد که این دو چه کاری انجام میدهند! استفاده از اینترفیس IRepository و تزریق وابستگی چه سودی در پروژه داره؟ واقعا نمیتونم این موضوع رو درک کنم! اصلا تزریق وابستگی چی هست؟! بدون استفاده از اینترفیس نمیشه مفهوم Repository Pattern رو در پروژه پیاده کرد؟! خیلی گیج شدم! اگر کسی از دوستان میدونه واقعا ممنون میشم که جوابمو بده؛ لطف بزرگی میکنید.
bomb23
چهارشنبه 05 خرداد 1395, 07:18 صبح
سلام
ببینید خیلی ساده بگم فرض کنید چند تا کلاس دارید که قراره اتصال به بانک های مختلف رو عملیاتی کنند مثلا یکی بانک ملی یکی بانک ملت و... . حالا اگه DI نباشه چطوری میخواید کلاس مربوطه که انتخاب میشه رو توی کنترلرتون فراخونی کنید؟ البته راه های پیچیده ای داره که بشه اینکار رو کرد ولی یک راه خیلی ساده DI هست که شما میاید میگید من یه اینترفیس پرداخت بانکی دارم که یه سری عملیات داره و همه کلاس های بانکی از این ارث میبرن. بعد داخل کنترلرتون به جای اینکه کلاس های بانک ملی و... رو new کنید اون اینترفیس رو new میکنید و بعد اون کلاس مورد نظر رو اصطلاحا بهش inject میکنید.
hp1361
چهارشنبه 05 خرداد 1395, 07:54 صبح
با سلام
مفهوم Dependency Injection و ارتباط آن با Interface:
طرح مسئله : شما برنامه ای رو در نظر بگیرید که قراره اطلاعات خرید از یک فروشگاه رو در بانک اطلاعاتی ذخیره کنه. برای هر خرید نیاز هست که میزان تخفیف با استفاده از تابعی محاسبه و سپس در بانک اطلاعاتی ذخیره شود. لذا کلاسی با عنوان Order تعریف نموده که تابعی بنام Discount برای این منظور خواهد داشت.
public class Order
{
public int Discount(int price)
{
return price*20/100;
}
}
حال با توجه به منطق برنامه در قسمت های مختلف از این کلاس نمونه سازی شده (new) و از تابع Discount جهت محاسبه میزان تخفیف استفاده خواهد شد. بعد از مدتی مشتری(سفارش دهنده نرم افزار) اعلام میکند که فرمول محاسبه تغییر کرده و نیاز است با فرمول دیگری این عملیات اجام پذیرد. برای اعمال این تغییر چه خواهید کرد؟
1- تغییر کدهای نوشته شده در تابع Discount مربوط به کلاس Order
2- تعریف یک کلاس جدید (برای مثال NewOrder)
حالت اول : ممکن است تابع مورد نظر را برنامه نویس قبلی پروژه بسیار بد پیاده سازی کرده باشد و شما بعنوان برنامه نویس جدید، ترجیح بدهید از ابتدا تابع را پیاده سازی کنید.شاید برای مثال عنوان شده این تغییر به راحتی انجام پذیرد، اما در نظر بگیرید که این صرفاً یک مثال جهت تشریح مفهوم Dependency Injection می باشد و در برنامه های واقعی ممکن است تغییر توابع نوشته شده باگ های مختلف محاسباتی و ... به همراه داشته باشد. ضمن اینکه ممکن است تابع نوشته شده(با همان فرمول قبلی) مجدداً نیاز شود از آن استفاده گردد!(پس نمی توان به این راحتی آنرا پاک نموده و پیاده سازی جدید را بجای آن نوشت)
حالت دوم : اگر کلاس جدیدی بنام NewOrder نوشته شود علاوه بر اینکه کدهای قبلی تابع Discount کلس Order کماکان وجود خواهند داشت(پاک و حذف نمیگردد)، پیاده سازی آن با توجه به نیازهای جدید و البته مورد دلخواه شما انجام خواهد شد. اما اکنون مشکلی پیش خواهد آمد که سرآغاز بحث Dependency Injection ست.
در این حالت با توجه به اینکه در جای جای برنامه خود از کلاس Order استفاده کرده اید، به اصطلاح برنامه را به کلاس Order وابسته نموده اید!(در مفهوم کلی تر برنامه به این پیاده سازی وابستگی دارد). یعنی اینکه حالا شما باید بگردید و هر جا از کلاس Order نمونه سازی گردیده نام آنزا به NewOrder تغییر بدهید! این حالت را برای برنامه های بزرگ در نظر بگیرید!
در حالت دوم به مشکلات حالت اول فائق آمدیم اما کماکان مشکل وابستگی وجود داد. سوال : چگونه میشود این وابستگی را از بین برد؟ جواب هوشمندانه : وابستگی را بر عکس نمائیم! به این معنی که برنامه به کلاس وابسته نباشد بلکه کلاس به برنامه وابسته باشد! این معکوس نمودن یعنی چی؟ یعنی اینکه برنامه صرفاً مشخص کند کلاس مورد درخواستش چه شرایطی و ویژگی هایی داشته باشد ولاغیر.
سوال : چطور میتوان شرایط و ویژگی ها را تعیین کرد بدون آنکه اسمی از یک کلاس خاص برد؟(اگر اسم کلاس درون برنامه برده شود، دوباره وابستگی ایجاد خواهد شد!)
جواب : مفهومی بنام Interface!
با استفاده از اینترفیس ما میتوانیم ویژگی ها و توابعی را تعریف کنیم که قرار است یک کلاس آنرا پیاده سازی نماید. برای مثال ما اینترفیسی را تعریف می کنیم که میگوید هر کلاسی که قرار است آنرا پیاده سازی کند باید تابعی برای محاسبه تخفیف داشته باشد. حال اینکه چطور و چگونه پیاده سازی میکند ارتباطی به اینترفیس نخواهد داشت.
public interface IOrder
{
int Discount(int price);
}
تا اینجا مفهوم وابستگی، معکوس سازی وابستگی و ارتباط آن با Interface بیان شد. تزریق وابستگی(Dependency Injection) نیز مربوط می شود به نحوه معکوس سازی و استفاده از Interface ها برای این منظور.
موفق باشیم
OmMiD_MtWo
چهارشنبه 05 خرداد 1395, 09:51 صبح
از جوابهای کامل دوستان سپاسگذارم.
من کلاس زیر رو از سایت http://www.dotnetcurry.com/aspnet-mvc/1155/aspnet-mvc-repository-pattern-perform-database-operations برای استفاده برداشتم و طبق آموزش پیش رفتم ولی اینطور که الان این اینترفیس پیاده سازی شده باز هم به نوع مدل و کلید مربوط به اون مدل که به اینترفیس فرستاده میشه وابسته است! اینطور نیست؟ یعنی هر جا بخوام از متدهای این اینترفیس استفاده کنم باید نوع مدل رو هم تعیین کنم در صورتی که ماهیت اینترفیس طبق گفته ی شما این نیست که وابسته به نوع مدل باشه! چه جوری این این یانترفیس رو از وابستگی خارج کنم؟
namespace DataAccessLayer.Repositories
{
public interface IRepository<Tentity, in Tkey> where Tentity : class
{
IEnumerable<Tentity> Get();
Tentity Get(Tkey key);
void Add(Tentity entity);
void Remove(Tkey key);
void Remove(Tentity entity);
void Update(Tentity entity);
}
}
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.