Dependency Injection nima?
Dependency Injection (DI) — bu dasturlash usuli bo‘lib, u class ni o‘z dependency laridan mustaqil qiladi.

Class ichida object ni to‘g‘ridan-to‘g‘ri yaratish moslashuvchan emas. Chunki class aniq bir object ga bog‘lanib qoladi va keyin uni o‘zgartirish qiyin bo‘ladi. Agar boshqa object kerak bo‘lsa, class ni o‘zgartirishga to‘g‘ri keladi. Bu esa kodni qayta ishlatishni qiyinlashtiradi va test qilishni murakkab qiladi, chunki real object ni mock object bilan almashtirib bo‘lmaydi.
Interface ga bog‘lanish concrete class ga bog‘lanishdan ko‘ra moslashuvchanroq. Object-oriented tillar runtime paytida abstraction ni concrete implementation bilan almashtirish imkonini beradi. Kodni imkon qadar abstraction ga bog‘lash kerak, chunki bu kodni moslashuvchan va qayta ishlatish mumkin qiladi.
DI shuni qabul qiladi:
Tight coupling yomon.
Dependency ni dependent class ichida yaratish to‘g‘ri emas.
Dependency va ularning implementation lari haqidagi ma’lumot bir joyda boshqarilishi kerak.
Tight coupling — class lar bir-biriga juda kuchli bog‘langan holat. Bu ko‘pincha bitta class juda ko‘p ish qilganda yoki bir masala bir nechta class ga tarqalib ketganda yuz beradi.
Loose coupling — har bir class faqat o‘z vazifasini bajaradigan va boshqa class lardan mustaqil bo‘lgan dizayn. Bunday class ni alohida ishlatish va test qilish oson.
Interface lar decoupling qilish uchun juda foydali. Class lar concrete class orqali emas, interface orqali bog‘lansa, istalgan class shu interface ni implement qilib ishlay oladi.
Inversion of Control (IoC) — bu dizayn prinsipi bo‘lib, boshqaruvni teskari qilish orqali loose coupling ga erishadi.
Dependency Inversion Principle (DIP) shuni aytadi:
High-level module low-level module ga bog‘lanmasligi kerak.
Ikkalasi ham abstraction ga bog‘lanishi kerak.
Abstraction detail ga bog‘lanmasligi kerak.
Detail abstraction ga bog‘lanishi kerak.
Dependency Injection (DI) — bu IoC ni amalga oshiruvchi design pattern.
Yangi object kerak bo‘lganda, uning dependency lari concrete class lar bilan bog‘lanishi kerak. Bu ishni container bajarishi mumkin. Agar ma’lum bir type so‘ralsa, container kerakli implementation ni inject qiladi. Qaysi implementation ishlatilishi mapping orqali belgilanadi va uni o‘zgartirish oson.
Container:
Kerakli class dan object yaratadi
Dependency larni constructor, property yoki method orqali inject qiladi
Kerak bo‘lganda object ni dispose qiladi
Bu biz object larni qo‘lda yaratib, boshqarib yurmasligimiz uchun kerak.
Container quyidagi jarayonlarni qo‘llab-quvvatlaydi:
Register – Qaysi type uchun qaysi dependency ishlatilishini belgilaydi.
Resolve – Object ni qo‘lda yaratmaymiz. Container yaratadi, dependency larni inject qiladi va tayyor object ni qaytaradi.
Dispose – Object ning lifetime ini boshqaradi.
Service lifetime — service qancha vaqt yashashini bildiradi.
Uch xil lifetime bor:
Transient – Har safar so‘ralganda yangi object yaratiladi.
Singleton – Application davomida bitta object yaratiladi.
Scoped – Har bir request uchun bitta object yaratiladi.
Container misollari:
StructureMap
Unity
Ninject
Autofac
.NET Core Container
Oddiy misol:
Maqsad — Web API yaratish va u Service orqali album lar ro‘yxatini qaytarsin.
Services nomli class library yaratiladi.
Album class yaratiladi.
IAlbumService interface yaratiladi.
AlbumsService class IAlbumService ni implement qiladi.
WebAPI project yaratiladi.
Microsoft.Extensions.DependencyInjection package o‘rnatiladi.
Startup.cs ichida ConfigureServices metodida dependency register qilinadi:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IAlbumsService, AlbumsService>();
}Keyin AlbumController yaratiladi va dependency constructor orqali inject qilinadi.
Dependency Injection client ga concrete implementation haqida bilmaslik imkonini beradi. Bir implementation ni boshqasiga o‘zgartirish uchun yuqori qatlamni o‘zgartirish shart emas.
DI yordamida:
Kod moslashuvchan bo‘ladi
Test qilish osonlashadi
Kodni qayta ishlatish mumkin bo‘ladi
Maintain qilish osonlashadi