यह ध्यान दिया जाना चाहिए कि अनुशंसित तरीका विकल्प पैटर्न का उपयोग करना है । लेकिन ऐसे मामलों का उपयोग किया जाता है जहां इसके अव्यावहारिक (जब पैरामीटर केवल रनटाइम पर पता होते हैं, स्टार्टअप / संकलित समय पर नहीं) या आपको गतिशील रूप से एक निर्भरता को बदलने की आवश्यकता होती है।
इसका बहुत उपयोगी है जब आपको एक एकल निर्भरता (जैसे कि यह एक स्ट्रिंग, पूर्णांक या किसी अन्य प्रकार की निर्भरता हो) को बदलने की आवश्यकता होती है या एक 3 पार्टी लाइब्रेरी का उपयोग करते समय जो केवल स्ट्रिंग / पूर्णांक मापदंडों को स्वीकार करता है और आपको रनटाइम पैरामीटर की आवश्यकता होती है।
आप एक शॉर्टकट हाथ के रूप में CreateInstance (IServiceProvider, Object []) की कोशिश कर सकते हैं (यह सुनिश्चित नहीं है कि यह स्ट्रिंग मापदंडों / मूल्य प्रकारों / आदिम (int, float, string) के साथ काम करता है, अप्रयुक्त) (बस इसे आज़माया और अपने काम की पुष्टि की, यहां तक कि साथ कई स्ट्रिंग पैरामीटर) हाथ से हर एक निर्भरता को हल करने के बजाय:
_serviceCollection.AddSingleton<IService>(x =>
ActivatorUtilities.CreateInstance<Service>(x, "");
);
पैरामीटर (के अंतिम पैरामीटर CreateInstance<T>
/CreateInstance
) उन मापदंडों को परिभाषित करते हैं जिन्हें प्रतिस्थापित किया जाना चाहिए (प्रदाता से हल नहीं किया गया)। वे दिखाई देने के रूप में बाएं से दाएं लागू होते हैं (यानी पहले स्ट्रिंग को तत्काल टाइप किए जाने वाले प्रकार के पहले स्ट्रिंग-टाइप किए गए पैरामीटर के साथ बदल दिया जाएगा)।
ActivatorUtilities.CreateInstance<Service>
एक सेवा को हल करने के लिए और इस एकल सक्रियण के लिए डिफ़ॉल्ट पंजीकरणों में से एक को बदलने के लिए कई स्थानों पर उपयोग किया जाता है।
उदाहरण के लिए यदि आप एक वर्ग में नामित किया है MyService
, और यह है IOtherService
, ILogger<MyService>
निर्भरता के रूप में और आप सेवा को हल लेकिन के डिफ़ॉल्ट सेवा बदलना चाहते हैं IOtherService
(अपने कहना OtherServiceA
) के साथ OtherServiceB
, आप की तरह कुछ कर सकता है:
myService = ActivatorUtilities.CreateInstance<Service>(serviceProvider, new OtherServiceB())
तब पहले पैरामीटर को इंजेक्ट किया IOtherService
जाएगा OtherServiceB
, बल्कि इसके बजाय OtherServiceA
शेष पैरामीटर कंटेनर से आएंगे।
यह तब सहायक होता है जब आपके पास बहुत अधिक निर्भरता होती है और आप केवल किसी एक का विशेष उपचार करना चाहते हैं (अर्थात अनुरोध के दौरान या किसी विशिष्ट उपयोगकर्ता के लिए कॉन्फ़िगर किए गए मान के साथ डेटाबेस विशिष्ट प्रदाता को बदलें, ऐसा कुछ जिसे आप केवल चलाते समय और अनुरोध के दौरान जानते हैं और नहीं जब आवेदन बनाया गया है / शुरू)।
आप इसके बजाय फैक्टरी विधि बनाने के लिए ActivatorUtilities.CreateFactory (प्रकार, प्रकार []) विधि का उपयोग कर सकते हैं, क्योंकि यह बेहतर प्रदर्शन GitHub संदर्भ और बेंचमार्क प्रदान करता है ।
बाद में एक उपयोगी होता है जब प्रकार को बहुत बार हल किया जाता है (जैसे कि सिग्नलआर और अन्य उच्च अनुरोध परिदृश्यों में)। मूल रूप से आप एक के ObjectFactory
माध्यम से बनाएँगे
var myServiceFactory = ActivatorUtilities.CreateFactory(typeof(MyService), new[] { typeof(IOtherService) });
फिर उसे कैश करें (एक चर आदि के रूप में) और जहां जरूरत हो, उसे कॉल करें
MyService myService = myServiceFactory(serviceProvider, myServiceOrParameterTypeToReplace);
## अपडेट: बस इसे स्ट्रिंग्स और पूर्णांक के साथ काम करने की पुष्टि करने के लिए खुद की कोशिश की, और यह वास्तव में काम करता है। यहाँ मैंने जिस ठोस उदाहरण के साथ परीक्षण किया है:
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddTransient<HelloWorldService>();
services.AddTransient(p => p.ResolveWith<DemoService>("Tseng", "Stackoverflow"));
var provider = services.BuildServiceProvider();
var demoService = provider.GetRequiredService<DemoService>();
Console.WriteLine($"Output: {demoService.HelloWorld()}");
Console.ReadKey();
}
}
public class DemoService
{
private readonly HelloWorldService helloWorldService;
private readonly string firstname;
private readonly string lastname;
public DemoService(HelloWorldService helloWorldService, string firstname, string lastname)
{
this.helloWorldService = helloWorldService ?? throw new ArgumentNullException(nameof(helloWorldService));
this.firstname = firstname ?? throw new ArgumentNullException(nameof(firstname));
this.lastname = lastname ?? throw new ArgumentNullException(nameof(lastname));
}
public string HelloWorld()
{
return this.helloWorldService.Hello(firstName, lastName);
}
}
public class HelloWorldService
{
public string Hello(string name) => $"Hello {name}";
public string Hello(string firstname, string lastname) => $"Hello {firstname} {lastname}";
}
static class ServiceProviderExtensions
{
public static T ResolveWith<T>(this IServiceProvider provider, params object[] parameters) where T : class =>
ActivatorUtilities.CreateInstance<T>(provider, parameters);
}
प्रिंटों
Output: Hello Tseng Stackoverflow