Как использовать IServiceScopeFactory.CreateScope - PullRequest
0 голосов
/ 07 апреля 2020

У меня есть все oop, обрабатывающие "сообщения" из очереди. Дело в том, что каждый элемент очереди должен иметь свою собственную «область действия»

У меня сложилось впечатление, что именно это должна решить для меня фабрика области действия.

using (var scope = scopeFactory.CreateScope())
                {
                    //Capture the scope..
                    var sp = scope.ServiceProvider;

                    //Set up the customer context here 
                    //CurrentContext is registerd as scoped
                    //This will create a new instance of the object. 
                    var cc = sp.GetService<CurrentContext>();
                    cc.AssetName = info.SourceName;
                    cc.Customer = info.CustomerGuid;
                    cc.Env = info.Env;
                    //and I'm setting the need values. 

                    //Using the service provider generated from the scope factory 
                    //to get my 'worker'
                    var worker = sp.GetService<TaskGeneratorWorker>();

                    await worker.CreateTasks(info);
                }

В моей регистрации DI У меня есть что-то похожее на это.

services.AddHttpClient<Visavi_SF_REST_Endpoint_Helper>((sp, client) =>
            {

                //CurrentScope.ServiceProvider
                var service = sp.GetService<ICustomerDataService>();
                //Trying to get the "CurrentContex" set in the scope in the previouse snippet. 

                //This is now a 'new' instance of the CurrentContext and my values is 'lost'
                var customer = sp.GetService<CurrentContext>();

            });

Если я поставлю поставщика услуг, которого я создал на шаге 1, в глобальный параметр, и сошлюсь на то, что в обоих случаях он работает должным образом.

    STEP 1:
    globalSp = scope;
    var cc = globalSp.ServiceProvider.GetService<CurrentContext>()

    STEP 2:
    var customer = globalSp.ServiceProvider.GetService<CurrentContext>();

Очевидно, что я неправильно понял, как это должно работать. Я подумал, что поставщик услуг отправил в services.AddHttpClient тот же «охват», что и родитель, который пытается создать его.

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

Насколько я понимаю, что-то не так с методом AddHttpClint.

Я создал собственное расширение и фабрику, и она работала, как и ожидалось.

 public static IServiceCollection AddScopedMultitenantHttpClient<TOwner>(this IServiceCollection services, Action<ClientConfig<TOwner>> config, Action<IServiceProvider, HttpClient> preExec) where TOwner : class
        {

            var conf = new ClientConfig<TOwner>();
            config(conf);

            conf.HttpHandlers.ForEach(e => services.AddScoped(e.type));


            services.AddSingleton(conf);

            services.AddScoped<TOwner>(sp =>
            {
                var conf = sp.GetService<ClientConfig<TOwner>>();

                //Create the HttpHandlers for the client.. Just have to validate that it works first. 
                var httpClient = new HttpClient(new AvoidDisposeMessageHandler(conf.LastHandler));
                preExec(sp,httpClient);
                return ActivatorUtilities.CreateInstance<TOwner>(sp, new object[] { httpClient });
            });

            return services;

        }

Я уже сталкивался с этой проблемой раньше, но не знал, что это та же проблема ..

******* НЕ ИСПОЛЬЗУЙТЕ ******

вышеуказанный код в производстве ..


0 голосов
/ 08 апреля 2020

Сервис имеет свою жизнь. Существует три разных срока службы для применения разных стратегий для создания службы, показанных ниже. Microsoft предоставляет более подробную информацию о сроке службы .

  • Переходный процесс: Каждый раз, когда DI создает новый объект службы.
  • Singleton: В объекте DI существует только один объект службы, соответствующий указанному типу c.
  • Область: если тип стратегии зарегистрирован в стратегии с областью действия, в той же области действия создания аналогичны одноэлементному, но в разная область применения, она похожа на переходную. То есть, если вы получаете объекты службы одного и того же типа из объекта области действия, они одинаковы, если вы получаете их из разных областей, службы будут разными.

Я не знаю какое время жизни имеет CurrentContext Если он зарегистрирован по временному или временному времени жизни, получить тот же сервис сложно, если вы не сохраните ссылку на объект области, как в STEP 1.

Если вы хотите получить один и тот же объект в другой области , лучше зарегистрировать его как единый сервис.

services.AddSingleton<CurrentContext>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...