ASP.NET Core में ConfigureServices के अंदर इंस्टेंस को कैसे हल करें


103

क्या स्टार्टअप में विधि IOptions<AppSettings>से एक उदाहरण को हल करना संभव है ConfigureServices? आम तौर पर आप IServiceProviderइंस्टेंस को इनिशियलाइज़ करने के लिए उपयोग कर सकते हैं लेकिन जब आप सेवाएँ रजिस्टर कर रहे हों तो आपके पास इस स्तर पर नहीं है।

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(
        configuration.GetConfigurationSection(nameof(AppSettings)));

    // How can I resolve IOptions<AppSettings> here?
}

जवाबों:


154

आप इस BuildServiceProvider()पद्धति का उपयोग करके एक सेवा प्रदाता का निर्माण कर सकते हैं IServiceCollection:

public void ConfigureService(IServiceCollection services)
{
    // Configure the services
    services.AddTransient<IFooService, FooServiceImpl>();
    services.Configure<AppSettings>(configuration.GetSection(nameof(AppSettings)));

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

    // Resolve the services from the service provider
    var fooService = sp.GetService<IFooService>();
    var options = sp.GetService<IOptions<AppSettings>>();
}

इसके लिए आपको Microsoft.Extensions.DependencyInjectionपैकेज चाहिए ।


ऐसे मामले में जहां आपको बस कुछ विकल्पों को बांधने की जरूरत है ConfigureServices, आप इस Bindविधि का उपयोग कर सकते हैं :

var appSettings = new AppSettings();
configuration.GetSection(nameof(AppSettings)).Bind(appSettings);

यह कार्यक्षमता Microsoft.Extensions.Configuration.Binderपैकेज के माध्यम से उपलब्ध है ।


क्या होगा यदि आपको एप्लिकेशन के किसी अन्य भाग में इस सेवा को हल करने की आवश्यकता है? मुझे यकीन है कि यह सब कन्फिगर्स सर्विसेज () में नहीं किया गया है?
रे

1
@ फिर आप डिफॉल्ट डिपेंडेंसी इंजेक्शन मैकेनिज्म जैसे कंस्ट्रक्टर इंजेक्शन का इस्तेमाल कर सकते हैं। यह प्रश्न विशेष रूप से ConfigureServicesविधि के अंदर सेवाओं को हल करने के बारे में है।
हेन्क मोल्लेमा

@ pcdev जब आप ऐसा करते हैं तो आप NULL हो जाते हैं और फिर आवृत्ति को हल करने का प्रयास करते हैं। आपको पहले सेवा को जोड़ना होगा।
इंगो

@IngoB हाँ, क्षमा करें, वह टिप्पणी गलत थी और उसे हटा दिया जाना चाहिए - मुझे ठीक से समझ नहीं आया कि उस टिप्पणी को लिखने पर क्या हो रहा था। कृपया वह उत्तर देखें जो मैंने पहले से जोड़ा है जिसे मैंने अपडेट किया है - मैंने कुछ और जांच की और अब इसे बेहतर समझ रहा हूं।
पीसीबीदेव

15
हालांकि यह उन मामलों में उपयोगी हो सकता है जहां सेवा जोड़ने की विधि में कार्यान्वयन कारखाना अधिभार नहीं है (जैसे, यहाँ ), BuildServiceProviderएक चेतावनी का उपयोग करते हुए यदि आवेदन कोड में उपयोग किया जाता है जैसे ConfigureServicesकि यह सिंगलटन सेवाओं की एक अतिरिक्त प्रतिलिपि के परिणामस्वरूप होता है। बनाया था। एहसान मिर्सैदी का जवाब यहां इस तरह के मामलों के लिए सबसे आदर्श समाधान है।
नियो

67

वर्गों है कि अन्य सेवाओं पर निर्भर हैं instantiating के लिए सबसे अच्छा तरीका है का उपयोग है जोड़ें XXX अधिभार है कि आप के साथ प्रदान करता है IServiceProvider । इस तरह आपको एक मध्यवर्ती सेवा प्रदाता को तत्काल करने की आवश्यकता नहीं है।

निम्नलिखित नमूने दिखाते हैं कि आप इस अधिभार को AddSingleton / AddTransient विधियों में कैसे उपयोग कर सकते हैं ।

services.AddSingleton(serviceProvider =>
{
    var options = serviceProvider.GetService<IOptions<AppSettings>>();
    var foo = new Foo(options);
    return foo ;
});


services.AddTransient(serviceProvider =>
{
    var options = serviceProvider.GetService<IOptions<AppSettings>>();
    var bar = new Bar(options);
    return bar;
});

16
.Net Core 3 या उच्चतर के लिए स्वीकृत उत्तर के बजाय इस समाधान का उपयोग करें!
जोशित

7
@ जोशित मुझे यकीन नहीं है कि यह सभी परिदृश्यों में स्वीकृत उत्तर के लिए एक व्यवहार्य प्रतिस्थापन है। IServiceProvider यानी AddSingleton, AddScoped, AddTransient के लिए उपलब्ध है। लेकिन कई अन्य ऐड विधियाँ हैं जो इस अधिभार को नहीं प्रदान करती हैं, अर्थात AddCors, AddAuthentication, AddAuthorization।
Jpsy

1
@ जेपी आप असंबंधित चीजों को मिलाते हैं। AddCors, AddAuthentication और इतने पर मददगार हैं जो विभिन्न अंतर्निहित मिडलवेयर को तार करने के लिए पंजीकरण emthods के नीचे कॉल करते हैं। AddTransient, AddSingleton, AddScoped तीन पंजीकरण हैं (तीन आमतौर पर इस्तेमाल किए गए जीवनकाल के साथ)
Fab

यह सभी मामलों को कवर नहीं करता है। कृपया मेरे उत्तर को एक समाधान के लिए देखें ।
इयान केम्प

8

ASP.NET Core के सभी संस्करणों में इसे प्राप्त करने का सबसे सरल और सबसे सही तरीका है , IConfigureOptions<TOptions>इंटरफ़ेस को लागू करना । जबकि यह .NET कोर 1.0 के बाद से आसपास है, ऐसा लगता है कि बहुत कम लोग जानते हैं कि यह कैसे काम करता है जस्ट वर्क ™

एक उदाहरण के रूप में, आप एक कस्टम मॉडल सत्यापनकर्ता जोड़ना चाहते हैं जिसमें आपके आवेदन की अन्य सेवाओं में से एक पर निर्भरता है। प्रारंभ में यह असंभव लगता है - इसका कोई तरीका नहीं है IMyServiceDependencyक्योंकि आपके पास कोई एक्सेस नहीं है IServiceProvider:

public class MyModelValidatorProvider : IModelValidatorProvider
{
    public MyModelValidatorProvider(IMyServiceDependency dependency)
    {
        ...
    }
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.ModelValidatorProviders.Add(new MyModelValidatorProvider(??????));
    });
}

लेकिन "जादू" IConfigureOptions<TOptions>इसे इतना आसान बनाता है:

public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
    private IMyServiceDependency _dependency;

    public MyMvcOptions(IMyServiceDependency dependency)
        => _dependency = dependency;

    public void Configure(MvcOptions options)
        => options.ModelValidatorProviders.Add(new MyModelValidatorProvider(_dependency));
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    ...

    // or scoped, or transient, as necessary for your service
    services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
}

अनिवार्य रूप से, Add***(***Options)प्रतिनिधियों में आपके द्वारा किया गया कोई भी सेटअप ConfigureServicesअब आपकी IConfigureOptions<TOptions>कक्षा की Configureपद्धति में चला जाएगा। फिर आप उसी तरह से विकल्पों को पंजीकृत करते हैं जैसे आप किसी अन्य सेवा को पंजीकृत करते हैं, और आप चले जाते हैं!

अधिक विस्तार के लिए, साथ ही साथ पर्दे के पीछे यह कैसे काम करता है, इस बारे में जानकारी के लिए, मैं आपको हमेशा उत्कृष्ट एंड्रयू लॉक का संदर्भ देता हूं


1

क्या आप निम्नलिखित जैसी किसी चीज़ की तलाश कर रहे हैं? आप कोड में मेरी टिप्पणियों पर एक नज़र डाल सकते हैं:

// this call would new-up `AppSettings` type
services.Configure<AppSettings>(appSettings =>
{
    // bind the newed-up type with the data from the configuration section
    ConfigurationBinder.Bind(appSettings, Configuration.GetConfigurationSection(nameof(AppSettings)));

    // modify these settings if you want to
});

// your updated app settings should be available through DI now

-1

दूसरों की मदद करना चाहते हैं जो एक ही चीज को देखते हैं लेकिन जब ऑटोफेक का उपयोग करते हैं।

आप कॉल करने की आवश्यकता आप ILifetimeScope (वर्तमान दायरे से यानी कंटेनर) प्राप्त करना चाहते हैं app.ApplicationServices.GetAutofacRoot()में विधि Configure(IApplicationBuilder app)आप संकल्प सेवाओं के लिए उपयोग कर सकते हैं इस ILifetimeScope उदाहरण वापस आ जाएगी

public void Configure(IApplicationBuilder app)
    {
        //app middleware registrations 
        //...
        //

        ILifetimeScope autofacRoot = app.ApplicationServices.GetAutofacRoot();
        var repository = autofacRoot.Resolve<IRepository>();
    }

1
यह जवाब ऑटोफेक के लिए बहुत अधिक स्पष्ट है, जो इस प्रश्न के दायरे में नहीं है।
शुद्ध.क्रोम

मैं इस सवाल को ऑटोफैक उपसर्ग के साथ देखने आया था और दुर्भाग्य से कोई विशिष्ट विषय नहीं मिला। इसलिए मुझे उम्मीद है कि इस समस्या से जूझ रहे अन्य लोगों को भी इसका जवाब मिल जाएगा।
बस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.