paint-brush
ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर के लिए जानने योग्य टिप्सद्वारा@devleader
764 रीडिंग
764 रीडिंग

ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर के लिए जानने योग्य टिप्स

द्वारा Dev Leader12m2024/05/10
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

जानें कि ASP.NET Core में Autofac ContainerBuilder का उपयोग निर्भरता इंजेक्शन को वायर अप करने के लिए कैसे करें। मैं पता लगाऊंगा कि हम इस दृष्टिकोण के साथ क्या कर सकते हैं और क्या नहीं!
featured image - ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर के लिए जानने योग्य टिप्स
Dev Leader HackerNoon profile picture
0-item


हमारे अनुप्रयोगों के अंदर निर्भरता इंजेक्शन को प्रबंधित करने के कई तरीके हैं, और मुझे लगता है कि विभिन्न तरीकों के लाभों और सीमाओं को समझना महत्वपूर्ण है। सुझाए गए AutofacServiceProviderFactory का उपयोग करने के बजाय ASP.NET Core में Autofac ContainerBuilder का उपयोग करके अपनी निर्भरता को संरचित करने का प्राथमिक तरीका एक ऐसा तरीका है जिसे हम तलाश सकते हैं!


इस लेख में, मैं आपके ASP.NET कोर एप्लिकेशन में AutofacServiceProviderFactory के बजाय Autofac के ContainerBuilder का उपयोग करने के तरीके पर प्रकाश डालता हूँ। हम देखेंगे कि आप इस दृष्टिकोण के साथ क्या कर सकते हैं और क्या नहीं कर सकते हैं, जबकि निर्भरता इंजेक्शन के साथ हमारे पास अन्य दृष्टिकोण उपलब्ध हैं।


यह एक श्रृंखला का हिस्सा होगा जहाँ मैं ASP.NET Core के अंदर Autofac के साथ निर्भरता समाधान का पता लगाऊँगा। मैं नीचे दी गई श्रृंखला को शामिल करना सुनिश्चित करूँगा क्योंकि मुद्दे प्रकाशित होते हैं:


इस श्रृंखला के अंत में, आप ASP.NET Core और Blazor के अंदर प्लगइन आर्किटेक्चर का अधिक आत्मविश्वास से पता लगाने में सक्षम होंगे, जो आपके लिए अन्वेषण करने के लिए और भी अधिक सामग्री प्रदान करेगा।


AutofacServiceProviderFactory के साथ समस्या

निष्पक्षता से कहें तो, अनुभाग का शीर्षक *लगभग* क्लिक-बेट है। मुझे लगता है कि आपके ASP.NET कोर अनुप्रयोगों में Autofac को सेट करने के लिए सुझाए गए तरीके के रूप में AutofacServiceProviderFactory उपयोग किया जाना अधिकांश अनुप्रयोगों के लिए बहुत अच्छा है। अधिकांश डेवलपर्स जो Autofac को अपनी पसंद के निर्भरता इंजेक्शन फ्रेमवर्क के रूप में उपयोग करना चाहते हैं, उन्हें इस तरह से बहुत अधिक समस्याओं का सामना नहीं करना पड़ेगा।


यह हमें ये क्षमता प्रदान करता है:

  • WebApplicationBuilder (और इस समय उपलब्ध किसी भी चीज़) तक पहुँचें
  • IConfiguration के इंस्टैंस तक पहुंच ( WebApplicationBuilder इंस्टैंस से भी उपलब्ध)
  • निर्भरता को न्यूनतम API पर स्थानांतरित करने की क्षमता


लेकिन मेरे लिए सबसे बड़ी समस्या यह है: हम WebApplication इंस्टेंस तक नहीं पहुँच सकते। जब मैं C# में प्लगइन आर्किटेक्चर बनाता हूँ, खास तौर पर ASP.NET कोर एप्लिकेशन बनाते समय, मैं रूट रजिस्टर करने के लिए WebApplication इंस्टेंस तक पहुँचना पसंद करता हूँ। इससे मैं अपने प्लगइन से कम से कम API को आसानी से रजिस्टर कर सकता हूँ, जिसके लिए तकनीकी रूप से केवल IEndpointRouteBuilder के कार्यान्वयन तक पहुँच की आवश्यकता होती है ताकि आसान सिंटैक्स प्राप्त किया जा सके।

क्या मैं इसके बिना गैर-न्यूनतम API पंजीकृत कर सकता हूँ? बिल्कुल। क्या समान सिंटैक्स प्रदान करने और WebApplication इंस्टेंस की आवश्यकता न होने का कोई और तरीका है? बहुत संभव है। लेकिन उस समस्या को हल करने की कोशिश करने के बजाय, मैं यह देखना चाहता था कि क्या मैं उस निर्भरता तक पहुँच प्राप्त कर सकता हूँ जिसमें मेरी रुचि है।


अब समय आ गया है कि मैं अपनी निर्भरता कंटेनर को स्थापित करने की योजना को बदलूं!


एक नमूना ASP.NET कोर अनुप्रयोग की खोज

आइए एक नमूना एप्लीकेशन देखें ताकि हमारे पास खोजने के लिए कुछ सामान्य आधार हो। यदि आपने पिछला लेख पढ़ा है, तो यह समान दिखाई देगा - नमूना मौसम एप्लीकेशन का एक रूपांतर:

 using Autofac; using Microsoft.AspNetCore.Mvc; // personal opinion: // I absolutely love having the entry point of my // applications being essentially: // - make my dependencies // - give me the primary dependency // - use it // - ... nothing else :) ContainerBuilder containerBuilder = new(); containerBuilder.RegisterModule<MyModule>(); using var container = containerBuilder.Build(); using var scope = container.BeginLifetimeScope(); var app = scope.Resolve<WebApplication>(); app.Run(); internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) { public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); } internal sealed class MyModule : Module { protected override void Load(ContainerBuilder containerBuilder) { containerBuilder.RegisterType<DependencyA>().SingleInstance(); containerBuilder.RegisterType<DependencyB>().SingleInstance(); containerBuilder.RegisterType<DependencyC>().SingleInstance(); containerBuilder .Register(ctx => { var builder = WebApplication.CreateBuilder(Environment.GetCommandLineArgs()); return builder; }) .SingleInstance(); containerBuilder .Register(ctx => ctx.Resolve<WebApplicationBuilder>().Configuration) .As<IConfiguration>() .SingleInstance(); containerBuilder .Register(ctx => { var builder = ctx.Resolve<WebApplicationBuilder>(); var app = builder.Build(); app.UseHttpsRedirection(); // FIXME: the problem is that the Autofac ContainerBuilder // was used to put all of these pieces together, // but we never told the web stack to use Autofac as the // service provider. // this means that the minimal API will never be able to // find services off the container. we would need to resolve // them BEFORE the API is called, like in this registration // method itself, from the context that is passed in. //DependencyA dependencyA = ctx.Resolve<DependencyA>(); // FIXME: But... What happens if something wants to take a // dependency on the WebApplication instance itself? Once the // web application has been built, there's no more adding // dependencies to it! var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; app.MapGet( "/weatherforecast", ( [FromServices] DependencyA dependencyA , [FromServices] DependencyB dependencyB , [FromServices] DependencyC dependencyC ) => { var forecast = Enumerable .Range(1, 5) .Select(index => new WeatherForecast ( DateOnly.FromDateTime(DateTime.Now.AddDays(index)), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)] )) .ToArray(); return forecast; }); return app; }) .SingleInstance(); } } internal sealed class DependencyA( WebApplicationBuilder _webApplicationBuilder); internal sealed class DependencyB( WebApplication _webApplication); internal sealed class DependencyC( IConfiguration _configuration);


इस दृष्टिकोण का एक आह्वान यह है कि हमारे प्राथमिक निर्भरता कंटेनर के रूप में ऑटोफैक ContainerBuilder वर्ग का उपयोग करने से हमें अपने प्रवेश बिंदु को संरचित करने का अवसर मिलता है:

  • कंटेनर निर्माण
  • निर्भरता पंजीकरण
  • प्राथमिक निर्भरता समाधान
  • ... ऐप शुरू करने के लिए एक ही विधि को कॉल करें!


मेरी राय में, यह आदर्श एप्लिकेशन स्टार्टअप कोड है। क्यों? क्योंकि आपको इसे छूने के लिए कभी भी यहाँ वापस आने की ज़रूरत नहीं है। कभी नहीं। चाहे आप इसमें कितनी भी चीज़ें जोड़ लें! और यह सब इसलिए है क्योंकि आप ज़्यादा मॉड्यूल लोड करने के लिए असेंबली को स्कैन कर सकते हैं।

पुनः, यह मेरी व्यक्तिगत पसंद है, और मैं यह दावा नहीं कर रहा हूं कि यह हर किसी का लक्ष्य होना चाहिए।

ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर की खामियां

बेशक, एक और तरीका जो पूरी तरह से बुलेटप्रूफ नहीं है। तो आइए चर्चा करते हैं कि ऑटोफ़ैक के इस सेटअप से हमें क्या नहीं मिलता है:

  • न्यूनतम API पर पारित सेवा-समाधान पैरामीटर बस काम नहीं करते हैं। जो WebApplication बनाया गया था, वह निर्भरता इंजेक्शन फ्रेमवर्क के रूप में ऑटोफ़ैक का उपयोग करने के लिए कॉन्फ़िगर नहीं किया गया है!
  • पिछले लेख की तरह, हम अभी भी निर्भरता कंटेनर पर WebApplication इंस्टेंस प्राप्त नहीं कर सकते हैं... इसलिए हमने उस तक पहुँचने के लिए कोई विशेष प्रगति नहीं की है।


लेकिन बस इतना ही! यह कमियों की एक भयानक सूची नहीं है, लेकिन ऑटोफ़ैक कंटेनरबिल्डर दृष्टिकोण हमारे लिए एक चांदी की गोली समाधान नहीं था। तो, हमें इससे क्या मिला? निम्नलिखित को समझाने में भी मदद करेगा:

ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर के लाभ

हम जो कुछ भी करते हैं उसके पक्ष और विपक्ष! अब जब हमने ASP.NET Core में Autofac ContainerBuilder के साथ समस्याओं को देखा है, तो यह देखने का समय है कि हमें इससे क्या प्रगति मिली है:


  • हम अभी भी WebApplicationBuilder और IConfiguration इंस्टैंस तक पहुंच सकते हैं, इसलिए यह AutofacServiceProviderFactory दृष्टिकोण का उपयोग करने के लिए एक तुलनीय लाभ है।
  • हम अपने प्रोग्राम के लिए एक बहुत ही सुव्यवस्थित प्रवेश बिंदु प्राप्त कर सकते हैं, जिसे मैं वास्तव में देखना पसंद करता हूँ। कंटेनर निर्माण, पंजीकरण, आपके प्रवेश बिंदु विधि का समाधान, और बस इतना ही!
  • न्यूनतम API काम करते हैं, लेकिन निर्भरताओं के साथ नहीं। फिर भी, हम न्यूनतम API द्वारा वांछित निर्भरताओं को पहले से हल कर सकते हैं और विधि पंजीकरण के समय उन्हें पास कर सकते हैं। टिप्पणी कोड देखें!

प्लगइन-आधारित ASP.NET रूट्स के लिए और अधिक व्युत्क्रमण?

हमने देखा कि हम ऑटोफ़ैक पंजीकरण विधि के भीतर न्यूनतम API पंजीकृत कर सकते हैं, लेकिन दुर्भाग्य से, हम सीधे न्यूनतम API कॉल पर कंटेनर से निर्भरता को हल नहीं कर सकते। हम निम्नलिखित की तरह एक समर्पित वर्ग बना सकते हैं जो निर्भरता को स्वचालित रूप से हल करने के साथ रूट परिभाषाओं को संभालता है:

 internal sealed class WeatherForecastRoutes( DependencyA _dependencyA // FIXME: still can't depend on this because // we can't get the WebApplication //, DependencyB _dependencyB , DependencyC _dependencyC) { private static readonly string[] _summaries = new[] { "Freezing", "Bracing", // ... }; public WeatherForecast[] Forecast() { var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast ( DateOnly.FromDateTime(DateTime.Now.AddDays(index)), Random.Shared.Next(-20, 55), _summaries[Random.Shared.Next(_summaries.Length)] )) .ToArray(); return forecast; } }


अगर हमारे पास यह क्लास और निर्भरताएँ सभी एक ही कंटेनर पर हैं, तो स्वचालित समाधान होता है। फिर यह केवल इस कोड को कॉल करने का मामला है:

 var weatherForecastRoutes = ctx.Resolve<WeatherForecastRoutes>(); app.MapGet("/weatherforecast2", weatherForecastRoutes.Forecast);


प्लगइन के नजरिए से यह अभी भी थोड़ा निराशाजनक है, क्योंकि हमें पंजीकरण कोड को कॉल करने के लिए सभी रूट क्लासों को मैन्युअल रूप से हल करना होगा - यह सब इस तथ्य से उपजा है कि ये चीजें WebApplication इंस्टेंस तक अपनी पहुंच को हल नहीं कर सकती हैं।


लेकिन रुकिए... क्या होगा अगर हम चीजों को पलट दें? क्या होगा अगर हम IRegisterRoutes जैसे कुछ इंटरफ़ेस को हल कर सकें और WebApplication इंस्टेंस में पास कर सकें?!

 // NOTE: make sure to register WeatherForecastRouteRegistrar on the // autofac container as IRegisterRoutes! internal interface IRegisterRoutes { void RegisterRoutes(WebApplication app); } internal sealed class WeatherForecastRouteRegistrar( WeatherForecastRoutes _weatherForecastRoutes) : IRegisterRoutes { public void RegisterRoutes(WebApplication app) { app.MapGet("/weatherforecast2", _weatherForecastRoutes.Forecast); } } // TODO: add this to the autofac code where the // WebApplication instance is built: foreach (var registrar in ctx.Resolve<IEnumerable<IRegisterRoutes>>()) { registrar.RegisterRoutes(app); }


अब, हमें इस बात की परवाह करने की भी ज़रूरत नहीं है कि WebApplication इंस्टेंस हमारे प्लगइन्स के लिए सुलभ है या नहीं! हो सकता है कि पहला संस्करण इतना सीमित न रहा हो। शायद हम यहाँ कुछ कर रहे हैं... हालाँकि, अगले लेख में इसे और विस्तार से समझाया जाना चाहिए।


ASP.NET कोर में ऑटोफैक कंटेनरबिल्डर को लपेटना

इस लेख में, मैंने AutofacServiceProviderFactory का उपयोग करने के बजाय स्पष्ट रूप से Autofac ContainerBuilder का उपयोग करने का पता लगाया, जैसा कि आमतौर पर सुझाया जाता है। हमने कुछ समान लाभ और कमियाँ देखीं, लेकिन विचार करने के लिए अलग-अलग चीज़ें भी थीं। प्रत्येक तरीका आपके आवेदन में आपकी ज़रूरत के हिसाब से फ़ायदे और नुकसान दे सकता है।


दिलचस्प बात यह थी कि अगर हम प्लगइन्स की दिशा में काम करने की कोशिश कर रहे हैं, तो हमें अपने प्लगइन्स से WebApplication इंस्टेंस तक पहुँचने की ज़रूरत ही नहीं पड़ेगी! अगर हम न्यूनतम API की परवाह करते हैं, तो यह अभी भी सीमित हो सकता है... लेकिन अन्यथा, हम एक दिलचस्प सोच पर हैं!

यदि आपको यह उपयोगी लगा और आप अधिक सीखने के अवसरों की तलाश कर रहे हैं, तो मेरे मुफ्त साप्ताहिक सॉफ्टवेयर इंजीनियरिंग न्यूज़लेटर की सदस्यता लेने पर विचार करें और यूट्यूब पर मेरे मुफ्त वीडियो देखें!