এএসপি.নেট কোর ডিআই সহ দৃষ্টান্তগুলি সমাধান করা


302

আমি কীভাবে এএসপি.নেট কোর এমভিসি অন্তর্নির্মিত নির্ভরতা ইনজেকশন ফ্রেমওয়ার্ক ব্যবহার করে কোনও প্রকারটি সমাধান করব?

ধারক সেট আপ করা যথেষ্ট সহজ:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddTransient<ISomeService, SomeConcreteService>();
}

তবে আমি ISomeServiceইঞ্জেকশন না দিয়ে কীভাবে সমাধান করব ? উদাহরণস্বরূপ, আমি এটি করতে চাই:

ISomeService service = services.Resolve<ISomeService>();

এ জাতীয় কোনও পদ্ধতি নেই IServiceCollection



3
আপনি কি সেগুলি ConfigureServices()পদ্ধতিতে (সহ IServiceCollection) বা অ্যাপ্লিকেশনটির কোথাও সমাধান করতে চান ?
হেন্ক মোল্লেমা

2
@ হেনকমোল্লেমা: শুরুতে যে কোনও জায়গায় আসলেই।
ডেভ নিউ

উত্তর:


484

IServiceCollectionইন্টারফেসের জন্য ব্যবহার করা হয় বিল্ডিং নির্ভরশীলতার ইনজেকশন ধারক। এটি সম্পূর্ণরূপে নির্মিত হওয়ার পরে, এটি কোনও IServiceProviderউদাহরণের সাথে রচিত হয় যা আপনি পরিষেবাগুলি সমাধান করতে ব্যবহার করতে পারেন। আপনি যে IServiceProviderকোনও ক্লাসে একটি ইনজেক্ট করতে পারেন । IApplicationBuilderএবং HttpContextশ্রেণীর পাশাপাশি সেবা প্রদানকারী প্রদান করতে পারেন, তাদের মাধ্যমে ApplicationServicesঅথবা RequestServicesযথাক্রমে বৈশিষ্ট্য।

IServiceProviderGetService(Type type)কোনও পরিষেবা সমাধানের জন্য একটি পদ্ধতি নির্ধারণ করে :

var service = (IFooService)serviceProvider.GetService(typeof(IFooService));

এ ছাড়াও আরও অনেক সুবিধা এক্সটেনশন যেমন প্রাপ্তিসাধ্য পদ্ধতি, হয় serviceProvider.GetService<IFooService>()(ক যোগ usingজন্য Microsoft.Extensions.DependencyInjection)।

স্টার্টআপ ক্লাসের ভিতরে পরিষেবাগুলি সমাধান করা

ইনজেকশন নির্ভরতা

রানটাইম এর হোস্টিং পরিষেবা প্রদানকারীর কন্সট্রাকটর মধ্যে কিছু পরিষেবায় উদ্বুদ্ধ করতে পারেন Startupযেমন বর্গ, IConfiguration, IWebHostEnvironment( IHostingEnvironmentপ্রাক 3.0 সংস্করণে), ILoggerFactoryএবং IServiceProvider। মনে রাখবেন যে উত্তরোত্তরটি হোস্টিং স্তর দ্বারা নির্মিত একটি উদাহরণ এবং এতে কোনও অ্যাপ্লিকেশন শুরু করার জন্য কেবল প্রয়োজনীয় পরিষেবা রয়েছে

ConfigureServices()পদ্ধতি সেবা ইনজেকশনের অনুমতি দেয় না, এটি শুধুমাত্র একটি গ্রহণ IServiceCollectionযুক্তি। ConfigureServices()আপনি আপনার অ্যাপ্লিকেশন দ্বারা প্রয়োজনীয় পরিষেবাগুলি নিবন্ধভুক্ত করার কারণেই এটি উপলব্ধি করে। তবে আপনি এখানে স্টার্টআপের কনস্ট্রাক্টারে ইনজেকশন করা পরিষেবাগুলি ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    // Use Configuration here
}

নিবন্ধভুক্ত যে কোনও পরিষেবা পদ্ধতিতে ConfigureServices()ইনজেকশন দেওয়া যেতে পারে Configure(); আপনি IApplicationBuilderপ্যারামিটারের পরে পরিষেবাগুলির একটি স্বেচ্ছাসেবী সংখ্যার যোগ করতে পারেন :

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IFooService>();
}

public void Configure(IApplicationBuilder app, IFooService fooService)
{
    fooService.Bar();
}

নির্ভরতা ম্যানুয়ালি সমাধান করা

আপনার যদি ম্যানুয়ালি পরিষেবাগুলি সমাধান করার প্রয়োজন হয় ApplicationServicesতবে IApplicationBuilderআপনার Configure()পদ্ধতিটি সরবরাহ করে প্রথমে ব্যবহার করা উচিত :

public void Configure(IApplicationBuilder app)
{
    var serviceProvider = app.ApplicationServices;
    var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}

IServiceProviderআপনার Startupক্লাসের কনস্ট্রাক্টরে একটি পাস এবং সরাসরি ব্যবহার করা সম্ভব , তবে উপরের হিসাবে এটিতে পরিষেবার একটি সীমাবদ্ধ উপসর্গ থাকবে এবং এইভাবে ব্যবহারের সীমিত ব্যবহার রয়েছে:

public Startup(IServiceProvider serviceProvider)
{
    var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}

আপনি যদি ConfigureServices()পদ্ধতিতে পরিষেবাদিগুলি সমাধান করতে চান তবে একটি পৃথক পদ্ধতির প্রয়োজন। আপনি উদাহরণটি IServiceProviderথেকে একটি মধ্যবর্তী তৈরি করতে পারেন IServiceCollectionযার মধ্যে পরিষেবা রয়েছে যা সেই বিন্দু পর্যন্ত নিবন্ধিত হয়েছে :

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IFooService, FooService>();

    // Build the intermediate service provider
    var sp = services.BuildServiceProvider();

    // This will succeed.
    var fooService = sp.GetService<IFooService>();
    // This will fail (return null), as IBarService hasn't been registered yet.
    var barService = sp.GetService<IBarService>();
}

দয়া করে নোট করুন: সাধারণত আপনার ConfigureServices()পদ্ধতির অভ্যন্তরে পরিষেবাগুলি সমাধান করা এড়ানো উচিত কারণ এটি সেই জায়গা যেখানে আপনি অ্যাপ্লিকেশন পরিষেবাদিটি কনফিগার করছেন । কখনও কখনও আপনার কেবলমাত্র একটি IOptions<MyOptions>দৃষ্টান্ত অ্যাক্সেস প্রয়োজন । আপনি IConfigurationউদাহরণ থেকে একটি দৃষ্টান্তের সাথে মানগুলি আবদ্ধ করে এটি সম্পাদন করতে পারেন MyOptions(বিকল্পগুলির ফ্রেমওয়ার্কটি যা মূলত এটি করে):

public void ConfigureServices(IServiceCollection services)
{
    var myOptions = new MyOptions();
    Configuration.GetSection("SomeSection").Bind(myOptions);
}

ম্যানুয়ালি সল্ভিং সার্ভিসেস (ওরফে সার্ভিস লোকেটার) সাধারণত একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচিত হয় । যদিও এটির ব্যবহারের ক্ষেত্রে (ফ্রেমওয়ার্ক এবং / বা অবকাঠামো স্তরগুলির জন্য) রয়েছে, আপনার যতটা সম্ভব এড়ানো উচিত।


14
@ হেনকমোল্লেমা তবে আমি যদি কিছু ইনজেকশান নাও করতে পারি, তবে আমার অর্থ হ'ল আমি ইনজেকশন দিতে পারি না IServiceCollection, এমন কিছু শ্রেণি যা ম্যানুয়ালি তৈরি করা হচ্ছে ( মাঝারি ওয়্যার স্কোপ ছাড়াই ), আমার ক্ষেত্রে একটি শিডিয়ুলার, যা সময়ে সময়ে কিছু সেবা প্রয়োজন এবং একটি ইমেল প্রেরণ করুন।
মেরদান গছমুরাদভ

52
সতর্কতা যদি আপনাকে পরিষেবাগুলিতে সমাধান করতে হয় ConfigureServicesএবং সেই পরিষেবাটি সিঙ্গলটন হয় তবে এটি আপনার Controllerব্যবহারের চেয়ে আলাদা সিঙ্গলটন হবে! আমি অনুমান এই কারণ এটি একটি ভিন্ন ব্যবহার IServiceProvider- এই এড়াতে মাধ্যমে সমাধান না করি BuildServiceProviderতাহলে এর পরিবর্তে থেকে Singleton আপনার লুকআপ সরাতে ConfigureServicesকরার Configure(..other params, IServiceProvider serviceProvider)মধ্যেStartup.cs
ওয়াল

3
@ ভাল ভাল পয়েন্ট। কারণ এটি ভিন্ন IServiceProviderউদাহরণ এটি একটি নতুন সিঙ্গলটন উদাহরণ তৈরি করবে। আপনি ConfigureServicesপদ্ধতিটি থেকে পরিষেবা সরবরাহকারীর উদাহরণটি ফিরিয়ে এড়াতে পারেন যাতে আপনার অ্যাপ্লিকেশনটিও যে পাত্রে ব্যবহৃত হয়।
হেন্ক মোল্লেমা

1
আমন্ত্রণ collection.BuildServiceProvider();ছিল যা আমার প্রয়োজন ছিল, ধন্যবাদ!
ক্রিস মেরিসিক

2
@ হেনকমোল্লেমা আপনি কীভাবে এটি কেবলমাত্র একটি পরিষেবা সরবরাহকারীর উদাহরণ দিয়ে কাজ করেন? সাধারণত, আপনি 1) আপনার নির্ভরতাগুলির কিছু নিবন্ধিত করুন 2) একটি অন্তর্বর্তীকালীন পরিষেবা সরবরাহকারীর উদাহরণ তৈরি করুন 3) আপনার অন্য কিছু নির্ভরতা নিবন্ধ করার জন্য প্রয়োজনীয় কিছু সমাধান করার জন্য সেই পরিষেবা সরবরাহকারীর ব্যবহার করুন। এরপরে, আপনি অন্তর্বর্তীকালীন দৃষ্টান্তটি ফিরিয়ে দিতে পারবেন না, কারণ এটি আপনার কিছু নির্ভরতা হারিয়েছে (3 তে নিবন্ধিত)। আমি কিছু অনুপস্থিত করছি?
ফিলিপ করুন

109

ম্যানুয়ালি সমাধানের উদাহরণগুলির মধ্যে IServiceProviderইন্টারফেসটি ব্যবহার করা জড়িত :

প্রারম্ভকালীন নির্ভরতা সমাধান করুন। কনফিগার সার্ভিসেস

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>();

    var serviceProvider = services.BuildServiceProvider();
    var service = serviceProvider.GetService<IMyService>();
}

শুরুতে নির্ভরতাগুলি সমাধান করুন on কনফিগার করুন

public void Configure(
    IApplicationBuilder application,
    IServiceProvider serviceProvider)
{
    // By type.
    var service1 = (MyService)serviceProvider.GetService(typeof(MyService));

    // Using extension method.
    var service2 = serviceProvider.GetService<MyService>();

    // ...
}

এএসপি.নেট কোর 3 এ স্টার্টআপ. কনফিগারে নির্ভরতাগুলি সমাধান করা

public void Configure(
    IApplicationBuilder application,
    IWebHostEnvironment webHostEnvironment)
{
    app.ApplicationServices.GetService<MyService>();
}

রানটাইম ইনজেক্টেড পরিষেবাদি ব্যবহার করা

কিছু ধরণের পদ্ধতি প্যারামিটার হিসাবে ইনজেকশন দেওয়া যেতে পারে:

public class Startup
{
    public Startup(
        IHostingEnvironment hostingEnvironment,
        ILoggerFactory loggerFactory)
    {
    }

    public void ConfigureServices(
        IServiceCollection services)
    {
    }

    public void Configure(
        IApplicationBuilder application,
        IHostingEnvironment hostingEnvironment,
        IServiceProvider serviceProvider,
        ILoggerFactory loggerfactory,
        IApplicationLifetime applicationLifetime)
    {
    }
}

নিয়ন্ত্রণকারী ক্রিয়ায় নির্ভরতাগুলি সমাধান করা

[HttpGet("/some-action")]
public string SomeAction([FromServices] IMyService myService) => "Hello";

1
@ আফসারমোহেব্বি GetServiceযা জেনেরিক তা হ'ল Microsoft.Extensions.DependencyInjectionনেমস্পেসে একটি এক্সটেনশন পদ্ধতি ।
আহমাদলি শাফিয়ে

সম্প্রসারণ পদ্ধতি সম্পর্কে: একটি এক্সটেনশন পদ্ধতি একটি স্ট্যাটিক পদ্ধতি যা কোনও শ্রেণিতে ফানকুনিয়ালিটি যুক্ত করে, আপনি সর্বজনীন স্থিত TheReturnType TheMethodName (এই TheTypeYouExtend theTypeYouExtend {// BODY declare এবং পরে আপনি এটি ব্যবহার করতে পারেন: TheTypeYouExtend.TheMethodName (); .NET কোরের সাথে একটি খুব সাধারণ অ্যাপ্রোচ হয়ে উঠুন, যাতে বিকাশকারীরা বেস কার্যকারিতা বাড়িয়ে তুলতে পারেন ... ভাল উদাহরণগুলি এখানে: ডকস.মাইক্রোসফটকম
জুয়ান

2
[FromServices]টীকা ঝরঝরে, ধন্যবাদ হয়!
ইয়ান কেম্প

17

আপনি যদি কোনও টেমপ্লেট সহ একটি অ্যাপ্লিকেশন তৈরি করেন তবে আপনার Startupক্লাসে এমন কিছু থাকবে :

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddMvc();
}

তারপরে আপনি সেখানে নির্ভরতা যুক্ত করতে পারেন, উদাহরণস্বরূপ:

services.AddTransient<ITestService, TestService>();

আপনি যদি ITestServiceনিজের কন্ট্রোলারে অ্যাক্সেস করতে চান তবে আপনি IServiceProviderকনস্ট্রাক্টরের সাথে যুক্ত করতে পারেন এবং এটি ইনজেকশন দেওয়া হবে:

public HomeController(IServiceProvider serviceProvider)

তারপরে আপনি যে পরিষেবাটি যুক্ত করেছেন তা সমাধান করতে পারেন:

var service = serviceProvider.GetService<ITestService>();

নোট করুন যে জেনেরিক সংস্করণটি ব্যবহার করতে আপনাকে এক্সটেনশনগুলির সাথে নাম স্থানটি অন্তর্ভুক্ত করতে হবে:

using Microsoft.Extensions.DependencyInjection;

ITestService.cs

public interface ITestService
{
    int GenerateRandom();
}

TestService.cs

public class TestService : ITestService
{
    public int GenerateRandom()
    {
        return 4;
    }
}

স্টার্টআপ.সি (কনফিগার সার্ভিস)

public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddMvc();

    services.AddTransient<ITestService, TestService>();
}

HomeController.cs

using Microsoft.Extensions.DependencyInjection;

namespace Core.Controllers
{
    public class HomeController : Controller
    {
        public HomeController(IServiceProvider serviceProvider)
        {
            var service = serviceProvider.GetService<ITestService>();
            int rnd = service.GenerateRandom();
        }

10

আপনি নিবন্ধভুক্ত অন্য নির্ভরতার কন্সট্রাক্টরের কাছে যাওয়ার উদ্দেশ্যে যদি কেবল একটি নির্ভরতা সমাধানের প্রয়োজন হয় তবে আপনি এটি করতে পারেন।

ধরা যাক আপনার একটি পরিষেবা ছিল যা স্ট্রিং এবং একটি আইসোম সার্ভিস নিয়েছিল।

public class AnotherService : IAnotherService
{
    public AnotherService(ISomeService someService, string serviceUrl)
    {
        ...
    }
}

আপনি যখন এটি স্টার্টআপ.স এর ভিতরে নিবন্ধন করতে যান, আপনাকে এটি করতে হবে:

services.AddScoped<IAnotherService>(ctx => 
      new AnotherService(ctx.GetService<ISomeService>(), "https://someservice.com/")
);

ওপি কনফিগার সার্ভিস পদ্ধতিতে কোনও পরিষেবা সমাধান করার প্রয়োজনীয়তার কারণটি প্রকাশ করে নি, তবে সম্ভবত
এটির

1
আসলে এটি গ্রহণযোগ্য উত্তর হওয়া উচিত ... যদিও হেন্ক মোল্লিমার উত্তরটি খুব উদাহরণস্বরূপ, আজকাল আপনার উত্তরটি ক্লিনার এবং একটি অন্তর্বর্তী আইএসসিওরপ্রাইডার (সিঙ্গেলনের বিভিন্ন উদাহরণ ...) নির্মাণ সম্পর্কিত সমস্যাগুলির পরিচয় দেয় না। সম্ভবত, হেন্ক উত্তর দিলে 2015 সালে এই সমাধানটি পাওয়া যায় নি, তবে এখন যাওয়ার উপায়।
vi100

এটি চেষ্টা ISomeServiceকরেছিলাম কিন্তু এখনও আমার জন্য নাল ছিল।
আজবিভেন

২ টি প্রশ্ন: ১) সার্ভিস শ্রেণির আন্ডার সার্ভিসের প্যারামিটার কনস্ট্রাক্টর যদি (সরানো বা সংযুক্ত পরিষেবাগুলি) পরিবর্তন করে, তবে আমাকে পরিষেবা আইএননসার সার্ভিসের রেজিস্টার বিভাগটি সংশোধন করা দরকার এবং এটি পরিবর্তিত হতে থাকে? ২) পরিবর্তে, আমি জনসাধারণের আন্ডার সার্ভিস (আইএস সার্ভিসপ্রোভাডার সার্ভিসপ্রাইভাইডার) এর মতো ১ টি প্যারামিটার সহ আরেকটি সার্ভিসের জন্য কেবলমাত্র একজন কনস্ট্রাক্টর যুক্ত করতে পারি এবং কনস্ট্রাক্টরের কাছ থেকে আমার প্রয়োজনীয় পরিষেবাগুলি পেতে পারি। এবং আমার কেবল স্টার্টআপ ক্লাসে পরিষেবাদির মতো সার্ভিস ক্লাস আন্ডারস সার্ভিসকে নিবন্ধিত করতে হবে .এডডটান্সিয়েন্ট <আইআনোথার সার্ভিস, আন্ডার সার্ভিস> (এসপি => service var পরিষেবা = নতুন আন্ডার সার্ভিস (এসপি); রিটার্ন সার্ভিস;});
থমাস.বেঞ্জ

2

আপনি এভাবে অনুমোদনের মতো বৈশিষ্ট্যগুলিতে নির্ভরতা ইনজেক্ট করতে পারেন

var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService));

এটিই আমি অনুসন্ধান করছিলাম .. ধন্যবাদ
রেয়ান চৌগল

0

আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমি অবাক হয়েছি যে একটি স্পষ্ট ও ঘৃণ্য হ্যাক এখানে নেই isn't

আপনি যখন আপনার সংজ্ঞাগুলি সংজ্ঞায়িত করেন তখন আপনার প্রয়োজনীয় পরিষেবাগুলি বের করার জন্য আপনার নিজস্ব সিটি ফাংশনটি সংজ্ঞায়িত করার দক্ষতাটি কাজে লাগাতে পারেন ... স্পষ্টতই আপনি যখন এই পরিষেবাটি অনুরোধ করেছিলেন তখনই এটি চালানো হবে আপনি যদি স্পষ্টভাবে মুছে ফেলা / সাফ না করেন এবং সংজ্ঞাটিকে আবার যুক্ত না করেন তবে শোষণকারী ctor প্রথম নির্মাণের মধ্যে এই পরিষেবা ।

পরিষেবার কনফিগারেশন চলাকালীন আপনাকে পরিষেবা ট্রি তৈরি করা বা এটি ব্যবহার করার প্রয়োজন নেই এই পদ্ধতির সুবিধা রয়েছে। কীভাবে পরিষেবাদিগুলি কনফিগার করা হবে তা আপনি এখনও নির্ধারণ করছেন।

public void ConfigureServices(IServiceCollection services)
{
    //Prey this doesn't get GC'd or promote to a static class var
    string? somevalue = null;

    services.AddSingleton<IServiceINeedToUse, ServiceINeedToUse>(scope => {
         //create service you need
         var service = new ServiceINeedToUse(scope.GetService<IDependantService>())
         //get the values you need
         somevalue = somevalue ?? service.MyDirtyHack();
         //return the instance
         return service;
    });
    services.AddTransient<IOtherService, OtherService>(scope => {
         //Explicitly ensuring the ctor function above is called, and also showcasing why this is an anti-pattern.
         scope.GetService<IServiceINeedToUse>();
         //TODO: Clean up both the IServiceINeedToUse and IOtherService configuration here, then somehow rebuild the service tree.
         //Wow!
         return new OtherService(somevalue);
    });
}

এই প্যাটার্নটি ঠিক করার উপায় হ'ল OtherServiceসুস্পষ্টভাবে IServiceINeedToUseতার উপর বা তার পদ্ধতির প্রত্যাবর্তনের মানের উপর নির্ভর করে ... বা সেই নির্ভরতা সুস্পষ্টভাবে অন্য কোনও ফ্যাশনে সমাধান করার পরিবর্তে তার উপর একটি সুস্পষ্ট নির্ভরতা দেওয়া।


-4
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddDbContext<ConfigurationRepository>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString")));

    services.AddScoped<IConfigurationBL, ConfigurationBL>();
    services.AddScoped<IConfigurationRepository, ConfigurationRepository>();
}

5
আপনার উত্তরগুলি গৃহীত হওয়ার সম্ভাবনা বেশি এবং সম্ভবত আপনি যদি কোনও কোড স্নিপেট নয়, কেন এটি একটি উত্তরের উত্তর বলে একটি সংক্ষিপ্ত বিবরণ প্রদান করেন । এটি প্রশ্নকারীকে নিশ্চিত হতে সহায়তা করে যে এটি তাদের জিজ্ঞাসিত প্রশ্নের উত্তর দিচ্ছে।
জিম এল

কেউ আপনার উত্তরটিকে নিম্ন-মানের হিসাবে ভুলভাবে পতাকাঙ্কিত করেছে। আপনার উত্তরটি আরও পতাকাঙ্কণ এবং / বা ডাউনভোটগুলি রোধ করতে কীভাবে কাজ করে তা বোঝাতে আপনার কিছু অনুষঙ্গযুক্ত পাঠ্য যুক্ত করা উচিত। কেবলমাত্র একটি কোডের উত্তরটি নিম্নমানের নয় । এটি প্রশ্নের উত্তর দেওয়ার চেষ্টা করে? যদি তা না হয় তবে 'উত্তর নয়' হিসাবে পতাকাঙ্কিত করুন বা মোছার প্রস্তাব দিন (যদি পর্যালোচনার সারিতে থাকে)। খ) এটি প্রযুক্তিগতভাবে ভুল? ডাউনভোট বা মন্তব্য করুন। পর্যালোচনা থেকে
ওয়াই হা লি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.