আমাদের অ্যাপ্লিকেশনগুলির মধ্যে নির্ভরতা ইনজেকশন পরিচালনা করার অনেক উপায় রয়েছে এবং আমি মনে করি বিভিন্ন পদ্ধতির সুবিধা এবং সীমাবদ্ধতাগুলি বোঝা গুরুত্বপূর্ণ। প্রস্তাবিত AutofacServiceProviderFactory
ব্যবহার করার পরিবর্তে আপনার নির্ভরতা গঠনের প্রাথমিক উপায় হিসাবে ASP.NET কোরে একটি Autofac ContainerBuilder
ব্যবহার করা হল এমন একটি পথ যা আমরা অন্বেষণ করতে পারি!
এই নিবন্ধে, আমি AutofacServiceProviderFactory এর পরিবর্তে আপনার ASP.NET কোর অ্যাপ্লিকেশনে Autofac-এর ContainerBuilder কীভাবে ব্যবহার করবেন তা হাইলাইট করছি। নির্ভরতা ইনজেকশনের সাথে আমাদের অ্যাক্সেস থাকা অন্যান্য পদ্ধতির বিপরীতে এই পদ্ধতির সাথে আপনি কী করতে পারেন এবং কী করতে পারবেন না তা আমরা দেখব।
এটি একটি সিরিজের অংশ হবে যেখানে আমি ASP.NET কোরের অভ্যন্তরে অটোফ্যাকের সাথে নির্ভরতা রেজোলিউশন অন্বেষণ করি। সমস্যাগুলি প্রকাশিত হওয়ার সাথে সাথে আমি নীচের সিরিজটি অন্তর্ভুক্ত করতে নিশ্চিত হব:
এই সিরিজের শেষে, আপনি আরও আত্মবিশ্বাসের সাথে ASP.NET কোর এবং ব্লেজারের ভিতরে প্লাগইন আর্কিটেকচারগুলি অন্বেষণ করতে সক্ষম হবেন, যা আপনাকে অন্বেষণ করার জন্য আরও বেশি সামগ্রী প্রদান করবে।
ন্যায্যভাবে বলতে গেলে, বিভাগের শিরোনামটি *প্রায়* ক্লিক-টোপ। আমি মনে করি যে AutofacServiceProviderFactory
আপনার ASP.NET কোর অ্যাপ্লিকেশনগুলিতে অটোফ্যাক সেট আপ করার প্রস্তাবিত উপায় হিসাবে ব্যবহৃত হচ্ছে বেশিরভাগ অ্যাপ্লিকেশনের জন্য দুর্দান্ত। বেশিরভাগ বিকাশকারী যারা অটোফ্যাককে তাদের পছন্দের নির্ভরতা ইনজেকশন ফ্রেমওয়ার্ক হিসাবে ব্যবহার করতে চান তারা এইভাবে অনেক সমস্যায় পড়বেন না।
এটি আমাদের করার ক্ষমতা বহন করে:
WebApplicationBuilder
অ্যাক্সেস করুন (এবং এই সময়ে উপলব্ধ কিছু)IConfiguration
উদাহরণে অ্যাক্সেস ( WebApplicationBuilder
উদাহরণ থেকেও উপলব্ধ)
কিন্তু আমার জন্য বড় সমস্যা: আমরা WebApplication
উদাহরণ অ্যাক্সেস করতে পারি না। যখন আমি C# এ প্লাগইন আর্কিটেকচার তৈরি করি, বিশেষ করে ASP.NET কোর অ্যাপ্লিকেশন তৈরি করার সময়, আমি রুট নিবন্ধন করার জন্য WebApplication
উদাহরণে অ্যাক্সেস পেতে চাই। এটি আমাকে সহজে আমার প্লাগইনগুলি থেকে ন্যূনতম API গুলি নিবন্ধন করতে দেয়, যা প্রযুক্তিগতভাবে সহজ সিনট্যাক্স পেতে শুধুমাত্র IEndpointRouteBuilder
এর বাস্তবায়নে অ্যাক্সেসের প্রয়োজন।
আমি কি এটি ছাড়া নন-ন্যূনতম API নিবন্ধন করতে পারি? একেবারে। অনুরূপ সিনট্যাক্স প্রদান করার অন্য উপায় আছে এবং একটি WebApplication
উদাহরণ প্রয়োজন হয় না? খুব সম্ভবত. কিন্তু সেই সমস্যাটির আশেপাশে কাজ করার চেষ্টা করার পরিবর্তে, আমি দেখতে চেয়েছিলাম যে আমি আগ্রহী সেই নির্ভরতার অ্যাক্সেস পেতে পারি কিনা।
এটা আমার নির্ভরতা ধারক সেট আপ কিভাবে পরিকল্পনা পরিবর্তন করার সময় ছিল!
আসুন একটি নমুনা অ্যাপ্লিকেশন দেখি যাতে আমাদের অন্বেষণ করার জন্য কিছু সাধারণ ভিত্তি থাকে। আপনি যদি পূর্ববর্তী নিবন্ধটি পড়ে থাকেন তবে এটি একই রকম দেখাবে — নমুনা আবহাওয়া অ্যাপ্লিকেশনের একটি পরিবর্তন:
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
ক্লাসটি আমাদের প্রাথমিক নির্ভরতা কন্টেইনার হিসাবে ব্যবহার করা আমাদের এন্ট্রি পয়েন্ট গঠন করার সুযোগ দেয়:
এটি, আমার মতে, আদর্শ অ্যাপ্লিকেশন স্টার্টআপ কোড। কেন? কারণ এটি স্পর্শ করার জন্য আপনাকে এখানে ফিরে আসতে হবে না। কখনো। আপনি কত জিনিস যোগ করুন না কেন! এবং এটি সব কারণ আপনি আরও মডিউল লোড করতে সমাবেশগুলি স্ক্যান করতে পারেন।
আবার, এটি আমার একটি ব্যক্তিগত পছন্দ, এবং আমি দাবি করার চেষ্টা করছি না যে এটি প্রত্যেকের লক্ষ্য হওয়া উচিত।
অবশ্যই, আরেকটি পদ্ধতি যা বেশ বুলেটপ্রুফ নয়। তাহলে আসুন আলোচনা করা যাক Autofac-এর এই সেটআপের সাথে আমরা কী পাব না:
WebApplication
টি তৈরি করা হয়েছিল সেটি অটোফ্যাককে নির্ভরতা ইনজেকশন ফ্রেমওয়ার্ক হিসাবে ব্যবহার করার জন্য কনফিগার করা হয়নি!WebApplication
দৃষ্টান্ত পেতে পারি না... তাই আমরা এটি অ্যাক্সেস করার বিষয়ে বিশেষভাবে কোনো অগ্রগতি করিনি।
কিন্তু যে বেশিরভাগই! এটি ত্রুটিগুলির একটি ভয়ানক তালিকা নয়, তবে Autofac ContainerBuilder পদ্ধতিটি আমাদের জন্য একটি রূপালী বুলেট সমাধান ছিল না। তাহলে, আমরা এর থেকে কী পেয়েছি? নিম্নলিখিত ব্যাখ্যা করতেও সাহায্য করবে:
আমরা যা কিছু করি তার জন্য সুবিধা এবং অসুবিধা! এখন যেহেতু আমরা ASP.NET কোরে Autofac ContainerBuilder-এর সমস্যাগুলি দেখেছি, এটি থেকে আমরা কী অগ্রগতি পেয়েছি তা দেখার সময় এসেছে:
WebApplicationBuilder
এবং IConfiguration
দৃষ্টান্তগুলি অ্যাক্সেস করতে পারি, যাতে এটি AutofacServiceProviderFactory
পদ্ধতি ব্যবহার করার একটি তুলনামূলক সুবিধা।আমরা দেখেছি যে আমরা একটি Autofac রেজিস্ট্রেশন পদ্ধতির মধ্যে ন্যূনতম 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
দৃষ্টান্তটি আমাদের প্লাগইনগুলিতে অ্যাক্সেসযোগ্য কিনা তাও আমাদের যত্ন নেওয়ার দরকার নেই! সম্ভবত প্রথম সংস্করণটি এত সীমাবদ্ধ ছিল না। হয়তো আমরা এখানে কিছু সম্মুখের... যাইহোক, পরবর্তী নিবন্ধ আরো বিস্তারিতভাবে এটি ব্যাখ্যা করা উচিত.
এই নিবন্ধে, আমি সাধারণত প্রস্তাবিত হিসাবে AutofacServiceProviderFactory
ব্যবহার করার পরিবর্তে স্পষ্টভাবে একটি Autofac ContainerBuilder
ব্যবহার করে অন্বেষণ করেছি। আমরা কিছু অনুরূপ সুবিধা এবং অপূর্ণতা দেখেছি, তবে বিবেচনা করার মতো একটি ভিন্ন সেটও। আপনি আপনার আবেদনের পরে কী করছেন তার উপর নির্ভর করে প্রতিটি উপায়ই ভালো-মন্দ অফার করতে পারে।
মজার বিষয় ছিল যে আমরা যদি প্লাগইনগুলির দিকে কাজ করার চেষ্টা করি তবে আমাদের প্লাগইনগুলি থেকে WebApplication
ইনস্ট্যান্স অ্যাক্সেস করার প্রয়োজনও নাও হতে পারে! আমরা যদি ন্যূনতম এপিআই সম্পর্কে যত্নশীল হই, তবে এটি এখনও সীমাবদ্ধ হতে পারে… তবে অন্যথায়, আমরা চিন্তার একটি আকর্ষণীয় লাইনে আছি!
আপনি যদি এটিকে দরকারী বলে মনে করেন এবং আপনি আরও শেখার সুযোগ খুঁজছেন, আমার বিনামূল্যের সাপ্তাহিক সফ্টওয়্যার ইঞ্জিনিয়ারিং নিউজলেটারে সদস্যতা নেওয়ার কথা বিবেচনা করুন এবং YouTube এ আমার বিনামূল্যের ভিডিওগুলি দেখুন!