कपल्ड (निर्भर) ऑब्जेक्ट्स को डिकपल्ड (स्वतंत्र) ऑब्जेक्ट्स में बदलने की प्रक्रिया को डिपेंडेंसी इंजेक्शन (DI) कहा जाता है।
डिपेंडेंसी इंजेक्शन के चार प्रकार
1. कंस्ट्रक्टर इंजेक्शन (सबसे आम और अनुशंसित)
कंस्ट्रक्टर का उपयोग इंटरफेस पैरामीटर को स्वीकार करने के लिए किया जाता है जो पैरामीटराइज्ड कंस्ट्रक्टर के माध्यम से एक्सपोज़ किया जाता है। यह ऑब्जेक्ट निर्माण के समय अन्य क्लासेस के रूप में निर्भरताओं को इंजेक्ट करता है।
public class Service : IService
{
private readonly IRepository _repository;
// निर्भरता कंस्ट्रक्टर के माध्यम से इंजेक्ट की जाती है
public Service(IRepository repository)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
}
2. सेटर इंजेक्शन (प्रॉपर्टी इंजेक्शन)
गेटर और सेटर इंजेक्शन डिफ़ॉल्ट पब्लिक प्रॉपर्टी प्रोसीजर जैसे get { } और set { } का उपयोग करके निर्भरता को इंजेक्ट करता है।
public class Service
{
public IRepository Repository { get; set; } // पब्लिक सेटर
public void DoWork()
{
Repository?.DoSomething(); // नल चेक आवश्यक
}
}
// उपयोग
var service = new Service();
service.Repository = new SqlRepository();
3. इंटरफेस-आधारित इंजेक्शन
इंटरफेस इंजेक्शन गेटर/सेटर DI के समान है, लेकिन गेटर/सेटर DI डिफ़ॉल्ट गेटर/सेटर का उपयोग करते हैं जबकि इंटरफेस इंजेक्शन एक सपोर्ट इंटरफेस का उपयोग करता है - एक तरह का एक्सप्लिसिट गेटर/सेटर जो इंटरफेस प्रॉपर्टी को सेट करता है।
public interface IInjectRepository
{
void SetRepository(IRepository repository);
}
public class Service : IInjectRepository
{
private IRepository _repository;
public void SetRepository(IRepository repository)
{
_repository = repository;
}
}
4. सर्विस लोकेटर इंजेक्शन
सर्विस लोकेटर इंजेक्शन को डिपेंडेंसी एब्सॉर्प्शन के रूप में भी जाना जाता है। यह new ऑपरेटर के प्रतिस्थापन के रूप में उपयोग किया जाता है। यह मेथड्स को सीधे इनवोक करके (ऑब्जेक्ट बनाए बिना) क्लास निर्भरता को छुपाता है।
public static class ServiceLocator
{
private static IServiceProvider _provider;
public static void SetLocatorProvider(IServiceProvider provider)
{
_provider = provider;
}
public static T GetService<T>()
{
return _provider.GetService<T>();
}
}
// उपयोग (एंटी-पैटर्न माना जाता है)
public class Service
{
public void DoWork()
{
var repo = ServiceLocator.GetService<IRepository>(); // छिपी हुई निर्भरता
repo.DoSomething();
}
}
DI के फायदे
| फायदा | विवरण |
|---|---|
| कम क्लास कपलिंग | क्लासेस ठोस कार्यान्वयन के बजाय अब्स्ट्रैक्शन पर निर्भर करती हैं |
| बढ़ी हुई कोड पुन: उपयोगिता | कंपोनेंट्स को अलग-अलग संदर्भों में पुन: उपयोग किया जा सकता है |
| बेहतर कोड मेंटेनेबिलिटी | बदलाव स्थानीयकृत होते हैं, रिपल इफेक्ट कम होता है |
| बेहतर एप्लिकेशन टेस्टिंग | मॉक/स्टब के साथ आसान यूनिट टेस्टिंग |
| केंद्रीकृत कॉन्फ़िगरेशन | निर्भरताएं एक स्थान पर कॉन्फ़िगर की जाती हैं (कंपोजिशन रूट) |
डिपेंडेंसी इंजेक्शन की कमियां
- जटिलता: कई इंस्टेंस और निर्भरताओं के साथ रिज़ॉल्यूशन मुश्किल हो जाता है
- प्रदर्शन: कंटेनर रिज़ॉल्यूशन में मामूली ओवरहेड
- सीखने की अवस्था: DI कंटेनर्स और पैटर्न्स को समझने की आवश्यकता
- रनटाइम त्रुटियां: गलत कॉन्फ़िगरेशन कंपाइल टाइम के बजाय रनटाइम पर विफल होता है
- "मैजिक" व्यवहार: नए लोगों के लिए नियंत्रण प्रवाह कम स्पष्ट
तुलना: कब किसका उपयोग करें
| प्रकार | सबसे अच्छा लिए | बचें जब |
|---|---|---|
| कंस्ट्रक्टर इंजेक्शन | अनिवार्य निर्भरताएं, अपरिवर्तनीयता | बहुत सारी निर्भरताएं (रीफैक्टर पर विचार करें) |
| सेटर इंजेक्शन | वैकल्पिक निर्भरताएं, रनटाइम परिवर्तन | निर्भरता ऑब्जेक्ट निर्माण के लिए आवश्यक है |
| इंटरफेस इंजेक्शन | फ्रेमवर्क एकीकरण, प्लगइन सिस्टम | सरल एप्लिकेशन |
| सर्विस लोकेटर | लेगेसी कोड, सीमित DI समर्थन | नए प्रोजेक्ट्स (एंटी-पैटर्न) |
आधुनिक C# / ASP.NET Core
// Program.cs - बिल्ट-इन DI कंटेनर
builder.Services.AddScoped<IRepository, SqlRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddSingleton<ICacheService, RedisCacheService>();
// कंट्रोलर में
public class HomeController : Controller
{
private readonly IRepository _repo;
private readonly IEmailService _email;
public HomeController(IRepository repo, IEmailService email)
{
_repo = repo;
_email = email;
}
}