بررسی طول عمر سرویس Transient, Singleton & Scoped

بررسی طول عمر سرویس Transient, Singleton & Scoped در Microsoft Dependency Injection Container و اکثر DI Container‌های دیگر، 3 نوع کلی چرخه‌ی حیات وجود دارند که به ترتیب پایداری و طول عمر شیء ایجاد شده، در زیر آورده شده‌اند:SingletonScopedTransientو اما NET. از design pattern تزریق وابستگی (DI) پشتیبانی می کند، که تکنیکی برای دستیابی به وارونگی کنترل (IoC) بین کلاس ها و وابستگی های آنهاست این فریم ورک دارای ویژگی های زیادی است که برای اکثر برنامه ها کافی است. اگر به ویژگی‌های بیشتری نیاز دارید، می‌توانید مستقیماً از دیگر کتابخانه‌های تزریق وابستگی شخص ثالث(3rd party/third party) استفاده کنید. توصیه می‌کنم از کتابخانه تزریق وابستگی Net. پیش‌فرض که سبک وزن و کارآمد است، استفاده کنید، مگر اینکه به ویژگی‌های اضافی و سفارشی(custom service lifetimes) نیاز داشته باشید.هر زمان که ما درخواست سرویس می کنیم، DI Container باید تصمیم بگیرد که آیا نمونه جدیدی از سرویس را برگرداند یا یک نمونه موجود را ارائه دهد. طول عمر سرویس به این بستگی دارد که چگونه وابستگی را نمونه سازی کنیم. ما در هنگام ثبت سرویس، طول عمر را تعیین می کنیم.یک) Singleton : یک سرویس جدید را فقط یک بار در طول عمر برنامه ایجاد می کند و در همه جا از آن استفاده می کند.دو) Scoped: یک نمونه جدید برای هر درخواست ایجاد می کند. و در آن درخواست مجددا استفاده می شود.سه) Transient: هر بار که شما آن را درخواست می کنید یک نمونه جدید از سرویس ایجاد می کند.ما می توانیم این سرویس ها را به ترتیب با متدهای ()AddTransient()، AddScoped و ()AddSingleton ثبت کنیم.طول عمر سرویس Transient, Singleton & Scopedدر حالی که یک نمونه singleton طول عمر برنامه را دارد، یک نمونه Scoped در یک درخواست زندگی می کند. در مورد یک نمونه Transient ، هر بار که ما آن را درخواست می کنیم ایجاد می شود - به عنوان مثال، هر زمان که به یک controller یا یک service تزریق شود.مقایسه Service Lifetimesدر حال حاضر ممکن است از خود بپرسید "آیا باید از Transient یا Scoped استفاده کنم یا دقیقا کجا باید Singelton رو بکار ببرم ؟".بیائید به چند توصیه در مورد زمان استفاده از هر یک از آنها و زمان عدم استفاده از آنها نگاه کنیم.سرویس Singletonدر تصویر بالا، دیدیم که یک سرویس singleton فقط یک نمونه ایجاد می کند و آن را در سراسر برنامه به اشتراک می گذارد.( اشیاء Singleton برای هر شی و هر درخواست یکسان هستند)چه زمانی از آن استفاده کنم ؟از نظر تئوری، یک سرویس singleton کارآمدترین از حافظه است زیرا یک بار ایجاد می شود و در همه جا دوباره استفاده می شود. همچنین، زمانی که می‌خواهیم یک حالت در سطح برنامه را حفظ کنیم، این یک انتخاب عالی است. پیکربندی اپلیکیشن، سرویس لاگ، ذخیره داده ها و غیره از جمله سناریوهایی هستند که می توانیم از سرویس singleton استفاده کنیم.چه زمانی از آن استفاده نکنم ؟حتی اگر سرویس‌های singleton از منظر حافظه کارآمد باشند، باید مراقب آنها باشیم زیرا احتمال نشت حافظه(memory leaks) در طول زمان وجود دارد. بنابراین ما همیشه باید قبل از طراحی سرویس singleton مراقب این موضوع باشیم. علاوه بر این، با سرویس singleton، این احتمال وجود دارد که با مسائل multi-threading نیز مواجه شوید. بنابراین اگر مطمئن نیستیم که سرویس و وابستگی‌های آن thread-safe هستند، هرگز نباید آنها را به‌عنوان singleton ثبت کنیم.(توصیه می کنم دو لینک ذیل الذکر را حتما مطالعه بفرمائید)برنامه نویسی موازی - بخش اول - مفاهیمبرنامه نویسی موازی بخش دوم (محافظت از مقادیر مشترک)نشت حافظه(memory leaks) : هنگامی که برنامه شما به اشیایی اشاره می کند که دیگر برای انجام وظیفه مورد نظر به آنها نیازی ندارد، ممکن است نشت حافظه رخ دهد. ارجاع دادن به اشیاء گفته شده باعث می شود سیستم زباله جمع کننده دات نت (garbage collector) نتواند حافظه استفاده شده را بازیابی کند، که اغلب منجر به کاهش عملکرد می شود و به طور بالقوه منجر به OutOfMemoryException می شود. این آموزش ابزارهایی را برای تجزیه و تحلیل نشت حافظه در یک برنامه NET Core با استفاده از ابزارهای تشخیصی CLI در دات نت نشان می دهد پیشنهاد می کنم بمنظور درک بهتر موضوع آن را مطالعه نمائید. سرویس Scopedیک نمونه جدید برای هر درخواست ایجاد می کند. و در آن درخواست مجددا استفاده می شود.(اشیاء Scoped در یک درخواست یکسان هستند، اما در درخواست های مختلف متفاوت هستند)چه زمانی از آن استفاده کنم ؟وقتی می‌خواهیم وضعیت را در یک درخواست حفظ کنیم، سرویس‌های Scoped انتخاب خوبی هستند. برای مثال، در نظر بگیرید که در یک درخواست چندین بار یک پایگاه داده را فراخوانی می کنیم. در این مورد، بهتر است از یک طول عمر محدوده استفاده کنید، زیرا همان شی را در حافظه نگه می دارد و در همان درخواست مجدداً از آن استفاده می کند.چه زمانی از آن استفاده نکنم ؟البته، اگر بخواهیم وضعیت را فراتر از یک درخواست واحد حفظ کنیم، یک سرویس scoped جواب نمی دهد و ما باید به سراغ singleton برویم.سرویس Transientهر بار که شما آن را درخواست می کنید یک نمونه جدید از سرویس ایجاد می کند.(اشیاء Transient همیشه متفاوت هستند. یک نمونه جدید برای هر سرویس ارائه می شود.)چه زمانی از آن استفاده کنم ؟ باید هنگام اجرای سرویس‌های سبک، انتخاب پیش‌فرض باشند، زیرا ایجاد و نگهداری آسان‌تر و کوتاه‌مدت هستند. مزیت دیگر این است که با طول عمر گذرا، ما نباید نگران سناریوهای multi-threading و نشت حافظه باشیم.چه زمانی از آن استفاده نکنم ؟از آنجایی که آنها با هر درخواست جدید ایجاد می شوند از حافظه و منابع بیشتری استفاده می کنند و می توانند تأثیر منفی بر عملکرد داشته باشند.پیاده سازی (Implementation)برای درک هرچه بیشتر مفاهیم گفته شده حتما مثال موجود در پروژه زیر را دانلود، بررسی و اجرا نمائید خروجی ها را ملاحظه و مقایسه نمایید، در ادامه صفحه مرورگر را refresh کنید، tab جدید باز کنید، iis را متوقف و مجددا start نمائید باز هم خروجی ها را با هم مقایسه نمائید. به وضوح متوجه تفاوت در LifeTime سرویس های Transient, Singleton & Scoped خواهید شد.لینک دانلود پروژه در githubقوانین زیر را به خاطر بسپاریدهرگز سرویس Scoped & Transient را به سرویس Singleton تزریق نکنید.هرگز سرویس Transient را به سرویس Scoped تزریق نکنیدبیشتر بخوانید : معرفی و بررسي IoC, DIP, DI ,IoC Containerبیشتر بخوانید : نقشه راه توسعه دهندگان Asp.net Corehttps://zarinp.al/farshidazizi