tgoop.com/fullStackDevs/631
Last Update:
#DI
#Ioc
#DIP
#SOLID
✳️ Captive Dependency
🔹 در این پست به توضیح مشکلی میپردازیم که معمولا به دلیل اشتباه کانفیگ کردن سرویس های اپلیکیشن در IOC Container رخ میدهد.
🔸 تزریق وابستگی (Dependency Injection) از مفاهیم مهمی هست که باید به آن آشنا باشیم. برای استفاده از این مفهوم و مفاهیم مرتبط با آن مثل IOC ,DIP
در اپلیکیشن، ابزار ها یا فریم وورک هایی وجود دارند که به آنها IOC Container می گوییم.
🔻اگر با DI و IOC و DIP آشنا نیستید مقالات لینک شده را مطالعه کنید.
🔸مدیریت lifeTime سرویس های اپلیکیشن امری است که به کمک IOC Container مقدر میشود اما وظیفه register کردن و معرفی کردن وابستگی ها به IOC Container بر عهده Developer میباشد.
🔸 اشتباه کانفیگ کردن lifeTime برای سرویسی در اپلیکیشن، که خود دارای وابستگی هایی، با lifeTime ای کمتر از lifeTime سرویس اصلی هستند، باعث به وجود آمد مشکل Captive Dependency میشود.
🔹 برای درک مسئله به مثال زیر توجه کنید
فرض کنید دو کلاس با نام های
ScopedDependency
SingletonDependency
داریم.
🔸 همانطور که از نام ها مشخص است کلاس SingletonDependency به صورت Singleton به DI Contaner معرفی شده و در طول عمر اپلیکیشن فقط یک نمونه از آن ساخته میشود.
🔸 کلاس ScopedDependency هم به صورت Scoped در IOC Container معرفی شده و به ازای هر connection به سرور فقط یک نمونه از آن به ازای هر کانکشن و درخواست ساخته میشود.
🔸 بیایید فرض کنیم که چه اتفاقی می افتد اگر کلاس SingletonDependency برای انجام برخی کارها در درون خود به کلاس ScopedDependency وابسته باشد و ما نیاز داشته باشیم که کلاس ScopedDependency در درون آن تزریق کنیم.
🔹 با رجیستر کردن کلاس ScopedDependency بصورت Scoped انتظار این است که روند نمونه سازی از این کلاس Scoped گونه باشد. اما وقتی این کلاس را در یک کلاس دیگر که به صورت Singleton رجیستر شده است تزریق میکنید، قوائد بازی را برهم زده و باعث میشوید که کلاس Singleton مورد نظر در تمام طول عمر خود فقط از یک نمونه قدیمی از وابستگی خود استفاده کند. این نمونه قدیمی برای اولین بار در هنگام ساخته شدن کلاس Singleton ای که در درون آن وجود دارد ساخته شده و به زندگی خود به لطف حضور در یک کلاس Singleton ادامه میدهد.
پس در نتیجه برای SingletonDepedency ما فقط یک نمونه از ScopedDependency ساخته میشود و در تمام طول عر خود از همان نمونه قدیمی استفاده میکند.
🔸در نگاه اول شاید این مشکل حاد به نظر نرسد اما باید بدانید که در یک پروژه که پیچیدگی های خاص خود را دارد باعث بروز مشکلات و باگ های فاحش خواهد شد.
🔸 این مشکل توسط Developer با اشتباه کانفیگ کردن lifeTime برای سرویس های اپلیکیشن رخ میدهد و حتی IOC Container هایی مانند Autofac نمی توانند از آن جلوگیری کنند.
اما IOC Container پیشفرض Asp.Net Core سعی کرده است تا حدی از این مشکل جلوگیری کند.
🔸 فعال سازی این ویژگی برای IOC Container پیشفرض اختیاری بوده و در صورت فعال سازی آن، نکته ای که باعث بهبود performance میشود این است که فقط در محیط و هنگام Development از آن استفاده کنید.
🔻همچنین باید بدانید که این ویژگی فقط از بروز Captive Dependency برای سرویس هایی که به صورت Scoped رجیستر شده اند، جلوگیری میکند و باعث صادر شدن استثنای InvalidOperationException میشود. و برای سرویس های که به صورت Transient رجیستر شده اند کار نمیکند.
❇️ برای فعال سازی این ویژگی در کلاس Program بدین شکل عمل کنید.
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseDefaultServiceProvider((env, c) =>
{
if (env.HostingEnvironment.IsDevelopment())
{
c.ValidateScopes = true;
}
});
}
@FullStackDevs
BY Web Devs
Share with your friend now:
tgoop.com/fullStackDevs/631