{"id":333843,"date":"2022-05-31T09:00:16","date_gmt":"2022-05-31T09:00:16","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=333843"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=333843","title":{"rendered":"<span>Dependency Injection \u0438 Full state \u0441\u0435\u0440\u0432\u0435\u0440<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/za\/yk\/yn\/zaykynpiqjdi3vab3e3yv-40wfe.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/za\/yk\/yn\/zaykynpiqjdi3vab3e3yv-40wfe.jpeg\" data-blurred=\"true\"\/><br \/>  \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u0441\u043e\u043e\u0431\u0449\u0443, \u0447\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f Fullstate \u0438 Stateless \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a\u0430\u044f-\u043b\u0438\u0431\u043e \u0430\u0433\u0438\u0442\u0430\u0446\u0438\u044f \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Fullstate. \u041c\u044b \u0438\u0441\u0445\u043e\u0434\u0438\u043c \u0438\u0437 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 ASP.NET \u0434\u043e\u043b\u0436\u0435\u043d \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443.<br \/>  \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u044e \u043c\u043e\u0449\u044c DI-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 .NET!<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h3 id=\"sessii\">\u0421\u0435\u0441\u0441\u0438\u0438<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u043d\u0435\u043a\u0438\u0439 \u043a\u043b\u044e\u0447 \u0432 \u0432\u0438\u0434\u0435 \u043a\u0443\u043a\u0438 \u0438\u043b\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u043e\u043f\u044f\u0442\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0431\u044b\u043b\u043e, \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>ASP.NET Core \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0443\u0436\u043d\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\/\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c, \u0430 \u0443\u0436 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e. <\/p>\n<p>  <\/p>\n<p>\u0412\u0430\u0440\u0438\u0430\u043d\u0442 \u0442\u0430\u043a\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u043a\u0430\u0447\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0411\u0414, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0430\u0440\u0442\u0438\u044f\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u043d\u0430\u0448\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u043c\u044b \u0440\u0435\u0448\u0430\u0435\u043c \u0432\u0441\u0451 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0438. \u041c\u044b \u043f\u0440\u043e\u0439\u0434\u0451\u043c \u043f\u0443\u0442\u044c \u043e\u0442 \u0438\u0434\u0435\u0438 \u0434\u043e \u0440\u0435\u043b\u0438\u0437\u0430.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u0434\u0435\u0438 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0444\u043e\u0440\u043c\u0438\u043c \u0432\u0441\u0451 \u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u043a\u0430\u043a \u0432 Microsoft.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u044b DI \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0432\u0441\u0451 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0430\u043a \u0436\u0435.<\/p>\n<p>  <\/p>\n<h3 id=\"upravlenie-sessiyami\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u044f\u043c\u0438<\/h3>\n<p>  <\/p>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441\u0435\u0441\u0441\u0438\u044f \u2014 \u044d\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u043e \u043a\u043b\u044e\u0447\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0443\u043a\u0438. \u041d\u0435\u043f\u043b\u043e\u0445\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 IMemoryCache, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, <\/li>\n<li>\u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u044e\u0447\u0435\u0439, \u0447\u0442\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e \u0441\u0435\u0441\u0441\u0438\u0439,<\/li>\n<li>\u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0432 ASP.NET Core DI \u0441 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0436\u0438\u0437\u043d\u0438 ServiceLifetime.Singleton.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 Visual Studio \u043f\u0443\u0441\u0442\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 ASP.NET Core. \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u0444\u0430\u0439\u043b Program.cs.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0434\u0443\u043c\u0430\u0435\u043c \u0438\u043c\u044f \u0434\u043b\u044f \u043a\u0443\u043a, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u044f \u0441\u0435\u0441\u0441\u0438\u0438 \u0434\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f 20 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0436\u0434\u0430\u0442\u044c \u0434\u043e\u043b\u0433\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">const string cookieName = \"qq\"; TimeSpan idleTimeout = TimeSpan.FromSeconds(20); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0411\u0443\u0434\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043a\u043b\u044e\u0447, \u0442\u043e \u0435\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0443\u043a\u0438 \u043a\u0430\u043a $&#187;{Guid.NewGuid()}:{Interlocked.Increment(ref cookieSequenceGen)}&#187;.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0442\u043e\u0439\u043a\u043e\u0441\u0442\u044c \u043a \u043f\u043e\u0434\u0431\u043e\u0440\u0443. \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">int cookieSequenceGen = 0;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u043f\u0446\u0438\u044e \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 IMemoryCache. \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0432 \u043d\u0435\u0439 callback, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0451 Dispose().<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">var entryOptions = new MemoryCacheEntryOptions()     .SetSlidingExpiration(idleTimeout); PostEvictionCallbackRegistration postEvictionCallbackRegistration =      new PostEvictionCallbackRegistration(); postEvictionCallbackRegistration.State = typeof(Program); postEvictionCallbackRegistration.EvictionCallback = (k, v, r, s) => {     if (r is EvictionReason.Expired &amp;&amp; s is Type sType          &amp;&amp; sType == typeof(Program)          &amp;&amp; v is IDisposable disposable)     {         disposable.Dispose();     } }; entryOptions.PostEvictionCallbacks.Add(postEvictionCallbackRegistration);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u043b\u0443\u0436\u0431\u0443 MemoryCache, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">var builder = WebApplication.CreateBuilder(args);  builder.Services.AddMemoryCache(op => {     op.ExpirationScanFrequency = TimeSpan.FromSeconds(1); });  builder.Logging.ClearProviders(); builder.Logging.AddConsole(op => {     op.TimestampFormat = \"[HH:mm:ss:fff] \"; });  var app = builder.Build(); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c middleware \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u0435\u0441\u0441\u0438\u0439. \u041f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u0441 \u0441\u0435\u0441\u0441\u0438\u0435\u0439 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0432\u0435\u0434\u0435\u043c \u043d\u0430 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0435: ID \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u043f\u0443\u0442\u044c, \u0441\u0435\u0441\u0441\u0438\u044e \u0438 \u0435\u0451 hashCode.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.Use(async (context, next) => {     IMemoryCache sessions =          context.RequestServices.GetRequiredService&lt;IMemoryCache>();     Session session = null;     int caseMatch = 0;     string key = context.Request.Cookies[cookieName];     bool isNewSession = false;     if (             key is null              || !sessions.TryGetValue(key, out object sessionObj)            || (session = sessionObj as Session) is null     )     {             key =                  $\"{Guid.NewGuid()}:{Interlocked.Increment(ref cookieSequenceGen)}\";             session =                  new(context.RequestServices.GetRequiredService&lt;ILogger&lt;Session>>());              context.Response.Cookies.Append(cookieName, key);             isNewSession = true;     }      ILogger&lt;Program> logger =          context.RequestServices.GetRequiredService&lt;ILogger&lt;Program>>();     logger.LogInformation($\"{context.Request.Path}: {session}({session.GetHashCode()})\");      try     {             await next?.Invoke();              if (isNewSession)              {                sessions.Set(key, session, entryOptions);             }     }     catch (Exception ex)     {             throw;     } }); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0430\u043f\u0438\u043c \u0440\u043e\u0443\u0442 \u0438 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.MapGet(\"\/\", async context => {     await context.Response.WriteAsync($\"Hello, World!\"); });  app.Run(); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0441\u0430\u043c\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u0442, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0438\u0448\u0435\u0442 \u0432 \u043b\u043e\u0433 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 Dispose():<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class Session : IDisposable {     private readonly ILogger&lt;Session> _logger;      public Session(ILogger&lt;Session> logger) => _logger = logger;     public void Dispose()     {             _logger.LogInformation($\"{this}({GetHashCode()}) disposed\");     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm1\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm1\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ed\/m1\/ov\/edm1ovn8r0pejx99tb1acncyt1e.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ed\/m1\/ov\/edm1ovn8r0pejx99tb1acncyt1e.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \/ \u0438 \/favicon.ico. \u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0441\u0435\u0441\u0441\u0438\u044f \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435. \u041d\u043e \u0447\u0435\u0440\u0435\u0437 20 \u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0439\u0434\u0451\u043c \u0435\u0449\u0451 \u0440\u0430\u0437:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kb\/vd\/ir\/kbvdirxuiswqk-sdycspzeu4boi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kb\/vd\/ir\/kbvdirxuiswqk-sdycspzeu4boi.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0432\u0435\u043b\u0430\u0441\u044c \u043d\u043e\u0432\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f, \u0430 \u0443 \u0441\u0442\u0430\u0440\u043e\u0439 Dispose() \u0432\u044b\u0437\u0432\u0430\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0439\u0447\u0430\u0441. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, callback \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438. \u042d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0441\u0435\u0441\u0441\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0431\u0443\u0434\u0438\u043b\u044c\u043d\u0438\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0430 \u0441 MemoryCache:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">... entryOptions.PostEvictionCallbacks.Add(postEvictionCallbackRegistration);  #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e System.Timers.Timer checkSessions = null!; TimeSpan checkSessionsInterval = TimeSpan.FromSeconds(1); #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e var builder = WebApplication.CreateBuilder(args); ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 middleware \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.Use(async (context, next) => {     IMemoryCache sessions = context.RequestServices.GetRequiredService&lt;IMemoryCache>();     #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     if (checkSessions is null)     {         lock (app)         {             if (checkSessions is null)             {                 checkSessions = new(checkSessionsInterval.TotalMilliseconds);                 checkSessions.Elapsed += (s, e) =>                 {                     sessions.TryGetValue(string.Empty, out object dumb);                 };                 checkSessions.Enabled = true;                 checkSessions.AutoReset = true;             }         }     }     #endregion  \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     Session session = null;    ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm2\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm2\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c Dispose() \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 ~20 \u0441\u0435\u043a\u0443\u043d\u0434, \u043a\u0430\u043a \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/gx\/pz\/1f\/gxpz1fnlcv71vjbveu30sopawe0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/gx\/pz\/1f\/gxpz1fnlcv71vjbveu30sopawe0.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"dostup-k-sessii\">\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0435\u0441\u0441\u0438\u0438<\/h3>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u0438, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0443\u0434\u0430-\u0442\u043e \u0438\u0445 \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u0438 \u043d\u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u043f\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c MemoryCache \u0441 \u043a\u0443\u043a\u0430\u043c\u0438, \u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0422\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 DI \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0436\u0438\u0437\u043d\u0438 \u0441\u0432\u043e\u0438\u0445 \u0441\u043b\u0443\u0436\u0431, \u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0442\u043e \u043c\u044b \u0435\u0451 \u043b\u0438\u0448\u0438\u043c\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class SessionHolder {     public Session Session { get; set; } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">... builder.Services.AddMemoryCache(op => {     op.ExpirationScanFrequency = TimeSpan.FromSeconds(1); });  #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e builder.Services.AddScoped&lt;SessionHolder>(); builder.Services.AddScoped&lt;Session>(op => op.GetRequiredService&lt;SessionHolder>().Session); #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e  builder.Logging.ClearProviders(); ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 middleware:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">    ...     logger.LogInformation($\"{context.Connection.Id}: {context.Request.Path}: {session}({session.GetHashCode()})\");     #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     context.RequestServices.GetRequiredService&lt;SessionHolder>().Session = session;     #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e      try    ... <\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.MapGet(\"\/\", async context => {     Session session = context.RequestServices.GetRequiredService&lt;Session>();     await context.Response.WriteAsync($\"Hello, World! {session}({session.GetHashCode()})\"); }); <\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm3\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm3\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ub\/dx\/89\/ubdx89apurubkzaubrolld40omy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ub\/dx\/89\/ubdx89apurubkzaubrolld40omy.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rz\/7u\/dc\/rz7udcvnnmrpwgbprnqrxpk7gjg.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rz\/7u\/dc\/rz7udcvnnmrpwgbprnqrxpk7gjg.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 DI \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 Dispose() \u0443 \u0441\u0435\u0441\u0441\u0438\u0438, \u043f\u043e\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 20 \u0441\u0435\u043a\u0443\u043d\u0434 \u0443 \u043d\u0435\u0451 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f Dispose() \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u043b\u0431\u044d\u043a\u0435. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e \u0438 \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c SessionHolder, \u0430 \u0443\u0436 \u0441\u0435\u0441\u0441\u0438\u044e \u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043d\u0435\u0433\u043e.<\/p>\n<p>  <\/p>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">... builder.Services.AddMemoryCache(op => {     op.ExpirationScanFrequency = TimeSpan.FromSeconds(1); });  builder.Services.AddScoped&lt;SessionHolder>(); #region \u0443\u0434\u0430\u043b\u0435\u043d\u043e \/\/builder.Services.AddScoped&lt;Session>(op => op.GetRequiredService&lt;SessionHolder>().Session); #endregion \u0443\u0434\u0430\u043b\u0435\u043d\u043e  builder.Logging.ClearProviders(); ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.MapGet(\"\/\", async context => {     Session session = context.RequestServices.GetRequiredService&lt;SessionHolder>().Session;     await context.Response.WriteAsync($\"[{DateTime.Now.ToString(\"HH:mm:ss.fff\")}] Hello, World! {session}({session.GetHashCode()})\"); }); <\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm4\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm4\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u0434\u0432\u0443\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/8x\/cd\/kf\/8xcdkfgjlkiyzlyoyvwhsgqvenc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/8x\/cd\/kf\/8xcdkfgjlkiyzlyoyvwhsgqvenc.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bp\/-o\/z9\/bp-oz9uyhnyrgg0bo2300qxvudu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bp\/-o\/z9\/bp-oz9uyhnyrgg0bo2300qxvudu.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/at\/fo\/yu\/atfoyu6kngtzfv0echzw34q8wh8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/at\/fo\/yu\/atfoyu6kngtzfv0echzw34q8wh8.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/g_\/vj\/qh\/g_vjqhrfklpgiyv3uc7reieadds.png\" data-src=\"https:\/\/habrastorage.org\/webt\/g_\/vj\/qh\/g_vjqhrfklpgiyv3uc7reieadds.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/qs\/bj\/8b\/qsbj8bnph2kdgelkehhrjorayye.png\" data-src=\"https:\/\/habrastorage.org\/webt\/qs\/bj\/8b\/qsbj8bnph2kdgelkehhrjorayye.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412\u0441\u0451 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u043f\u043e \u043f\u043b\u0430\u043d\u0443. <\/p>\n<p>  <\/p>\n<h3 id=\"problemy-s-konteynerom-di\">\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c DI<\/h3>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430. \u041c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e Http \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0438. \u0412\u0435\u0434\u044c \u0441 \u043d\u0438\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0441 \u0441\u0435\u0441\u0441\u0438\u0435\u0439 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0435\u0451 \u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0442\u0430\u043a \u0436\u0435. \u0418 \u0435\u0441\u043b\u0438 \u0441 \u043e\u0434\u043d\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u2014 Session \u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0438\u0440\u0438\u0442\u044c\u0441\u044f, \u0442\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0435\u0441\u0441\u0438\u044f\u0445, \u043c\u0438\u0440\u0438\u0442\u044c\u0441\u044f \u043c\u044b \u0443\u0436\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c. \u041d\u0430\u0434\u043e \u0438\u0434\u0442\u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0443\u0442\u0451\u043c!<\/p>\n<p>  <\/p>\n<p>\u0418\u043d\u0442\u0443\u0438\u0446\u0438\u044f \u043d\u0430\u043c \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0435\u0441\u0441\u0438\u0438 \u043d\u043e\u0432\u044b\u0439 scope \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0441\u043b\u0443\u0436\u0431 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI, \u0442\u043e \u0432\u0437\u044f\u0442\u044b\u0435 \u0438\u0437 \u043d\u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u044b\u0436\u0438\u0432\u0443\u0442 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0442\u0430\u043a \u043b\u0438 \u044d\u0442\u043e.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0441\u0435\u0441\u0441\u0438\u0438, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u0432\u043e\u0439 scope \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0441\u043b\u0443\u0436\u0431 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e Dispose() \u0432 \u043a\u043e\u043d\u0446\u0435 \u0436\u0438\u0437\u043d\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class Session : IDisposable {     private readonly ILogger&lt;Session> _logger;     public IServiceProvider SessionServiceProvider { get; init; }      public Session(IServiceProvider serviceProvider) =>         (SessionServiceProvider, _logger) = (serviceProvider,        serviceProvider.GetRequiredService&lt;ILogger&lt;Session>>());     public void Dispose()     {             if(SessionServiceProvider is IDisposable disposable)             {                disposable.Dispose();             }         _logger.LogInformation($\"{this}({GetHashCode()}) disposed\");     } } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043b\u0430\u0441\u0441 InfoProvider, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0436\u0438\u0442\u044c \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0430 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 Get(), \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0435\u0439 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class InfoProvider : IDisposable {     private ConcurrentQueue&lt;int> _queue = new();     private readonly CancellationTokenSource _cancellationTokenSource = new();     private Task _fill = null;     private readonly ILogger&lt;InfoProvider> _logger;     private readonly IServiceProvider _serviceProvider;      public InfoProvider(IServiceProvider serviceProvider)     {             _serviceProvider = serviceProvider;             _logger = _serviceProvider.GetRequiredService&lt;ILogger&lt;InfoProvider>>();             int value = 0;             CancellationToken cancellationToken = _cancellationTokenSource.Token;             _fill = Task.Run(async () =>             {                while (!cancellationToken.IsCancellationRequested)                {                   await Task.Delay(1000);                   _queue.Enqueue(++value);                }             });     }      public string Get()     {             Another another = _serviceProvider.GetRequiredService&lt;Another>();             _logger.LogInformation($\"{this}({GetHashCode()}) {another}({another.GetHashCode()})\");             List&lt;int> result = new();             while (_queue.TryDequeue(out int k))             {                result.Add(k);             }             return $\"{this}({GetHashCode()}) {another}({another.GetHashCode()}), {string.Join(\", \", result)}\";     }      public void Dispose()     {             _cancellationTokenSource.Cancel();             _fill.Wait();             _logger.LogInformation($\"{this}({GetHashCode()}) disposed\");     }  } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043b\u0430\u0441\u0441 Another, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 InfoProvider, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u2014 \u043d\u043e\u0432\u044b\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class Another : IDisposable {     private readonly ILogger&lt;Another> _logger;      public Another(ILogger&lt;Another> logger) => _logger = logger;     public void Dispose()     {             _logger.LogInformation($\"{this}({GetHashCode()}) disposed\");     } } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">... builder.Services.AddMemoryCache(op => {     op.ExpirationScanFrequency = TimeSpan.FromSeconds(1); });  builder.Services.AddScoped&lt;SessionHolder>(); #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e builder.Services.AddScoped&lt;InfoProvider>(); builder.Services.AddScoped&lt;Another>(); #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e  builder.Logging.ClearProviders(); ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 middleware \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">...     if (         key is null         || !sessions.TryGetValue(key, out object sessionObj)         || (session = sessionObj as Session) is null     )     {         key = $\"{Guid.NewGuid()}:{Interlocked.Increment(ref cookieSequenceGen)}\";         #region \u0443\u0434\u0430\u043b\u0435\u043d\u043e         \/\/ session = new(context.RequestServices.GetRequiredService&lt;ILogger&lt;Session>>());         #endregion \u0443\u0434\u0430\u043b\u0435\u043d\u043e         #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         session = new(context.RequestServices.CreateScope().ServiceProvider);         #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         context.Response.Cookies.Append(cookieName, key);         isNewSession = true;     }      ILogger&lt;Program> logger = context.RequestServices.GetRequiredService&lt;ILogger&lt;Program>>();  ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 Another \u0438 InfoProvider.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">app.MapGet(\"\/\", async context => {     Session session = context.RequestServices.GetRequiredService&lt;SessionHolder>().Session;     Another another = context.RequestServices.GetRequiredService&lt;Another>();     await context.Response.WriteAsync($\"[{DateTime.Now.ToString(\"HH:mm:ss.fff\")}] Hello, World! {session}({session.GetHashCode()})\"         + $\", controller {another}({another.GetHashCode()}), \"         + session.SessionServiceProvider.GetRequiredService&lt;InfoProvider>().Get()); }); <\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm5\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm5\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cm\/wj\/op\/cmwjopjoqispdh2hx1zzrugbir0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/cm\/wj\/op\/cmwjopjoqispdh2hx1zzrugbir0.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/a6\/mr\/2m\/a6mr2my7gyuqhd3eivxawjrrozq.png\" data-src=\"https:\/\/habrastorage.org\/webt\/a6\/mr\/2m\/a6mr2my7gyuqhd3eivxawjrrozq.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kp\/1i\/w6\/kp1iw6kc2ydfdb3s83cqip967ws.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kp\/1i\/w6\/kp1iw6kc2ydfdb3s83cqip967ws.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/as\/2b\/ci\/as2bcis5hr5s4elf_3rdo0drhce.png\" data-src=\"https:\/\/habrastorage.org\/webt\/as\/2b\/ci\/as2bcis5hr5s4elf_3rdo0drhce.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e Another, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u043d\u043e \u0442\u043e\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 InfoProvider, \u0436\u0438\u0432\u0451\u0442 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0441\u0435\u0441\u0441\u0438\u0438. \u042d\u0442\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u043e\u0442 Another \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u0435\u043c \u0436\u0435 scope, \u0447\u0442\u043e \u0438 InfoProvider.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 Session \u0442\u0430\u043a\u0436\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 DI \u0438\u0437 Http-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c Session:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class Session : IDisposable {     private readonly ILogger&lt;Session> _logger;     public IServiceProvider SessionServiceProvider { get; init; }     #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     public IServiceProvider RequestServiceProvider { get; set; }     #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e      public Session(IServiceProvider serviceProvider) =>         (SessionServiceProvider, _logger) = (serviceProvider, serviceProvider.GetRequiredService&lt;ILogger&lt;Session>>());     public void Dispose()     {         if (SessionServiceProvider is IDisposable disposable)         {             disposable.Dispose();         }         _logger.LogInformation($\"{this}({GetHashCode()}) disposed\");     } } <\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c middleware. \u041c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c Session \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0445\u043e\u043b\u0434\u0435\u0440\u0443 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 DI \u0438\u0437 Http-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u043d\u043e \u0438 \u0445\u043e\u043b\u0434\u0435\u0440\u0443 \u0438\u0437 scope, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0441\u0435\u0441\u0441\u0438\u044e. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0435\u0441\u0441\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 DI \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0436\u0438\u0432\u0443\u0449\u0438\u0445 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">...     if (         key is null         || !sessions.TryGetValue(key, out object sessionObj)         || (session = sessionObj as Session) is null     )     {         key = $\"{Guid.NewGuid()}:{Interlocked.Increment(ref cookieSequenceGen)}\";         session = new(context.RequestServices.CreateScope().ServiceProvider);         #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         session.SessionServiceProvider.GetRequiredService&lt;SessionHolder>().Session = session;         #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         context.Response.Cookies.Append(cookieName, key);         isNewSession = true;     }     #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     session.RequestServiceProvider = context.RequestServices;     #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e     context.RequestServices.GetRequiredService&lt;SessionHolder>().Session = session;      ILogger&lt;Program> logger = context.RequestServices.GetRequiredService&lt;ILogger&lt;Program>>();     logger.LogInformation($\"{context.Connection.Id}: {context.Request.Path}: {session}({session.GetHashCode()})\");      try ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c InfoProvider, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u043b Another \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI Http-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public string Get()     {         #region \u0443\u0434\u0430\u043b\u0435\u043d\u043e         \/\/ Another another = _serviceProvider.GetRequiredService&lt;Another>();         #endregion \u0443\u0434\u0430\u043b\u0435\u043d\u043e         Session session = _serviceProvider.GetRequiredService&lt;SessionHolder>().Session;         #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         Another another = session.RequestServiceProvider.GetRequiredService&lt;Another>();         #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         _logger.LogInformation($\"{this}({GetHashCode()}) {another}({another.GetHashCode()})\");         List&lt;int> result = new();         while (_queue.TryDequeue(out int k))         {             result.Add(k);         }         return $\"{this}({GetHashCode()}) {another}({another.GetHashCode()}), {string.Join(\", \", result)}\";     } <\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm6\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/sm6\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/sg\/ie\/ol\/sgieolt-qae0lq79aelkah7mgcq.png\" data-src=\"https:\/\/habrastorage.org\/webt\/sg\/ie\/ol\/sgieolt-qae0lq79aelkah7mgcq.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/gr\/a2\/hk\/gra2hkjs_io2n7wzcsfbufgqgr4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/gr\/a2\/hk\/gra2hkjs_io2n7wzcsfbufgqgr4.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ib\/bh\/qc\/ibbhqcgzwgl1tbxltpox9spppii.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ib\/bh\/qc\/ibbhqcgzwgl1tbxltpox9spppii.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043e!<\/p>\n<p>  <\/p>\n<h3 id=\"sozdanie-biblioteki\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/h3>\n<p>  <\/p>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436, \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0442\u044c\u0441\u044f \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 SOLID \u0438 \u0431\u0440\u0438\u0442\u0432\u043e\u0439 \u041e\u043a\u043a\u0430\u043c\u0430, \u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u0439\u0442\u0438 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043c\u044b \u0445\u0440\u0430\u043d\u0438\u043c \u0432 MemoryCache \u043e\u0431\u044a\u0435\u043a\u0442 Session \u0438\u0437-\u0437\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 SessionServiceProvider, \u043b\u043e\u0433\u0438\u0447\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0435\u0441\u0441\u0438\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a Scoped \u0438 \u0432 middleware \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430;<\/li>\n<li>\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 Session \u0438\u0437 Http \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0445\u043e\u0442\u044f \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043b\u044e\u0431\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0434\u0430\u0436\u0435 \u0432 \u0442\u043e\u043c, \u0437\u043d\u0430\u043d\u0438\u0435 \u043e\u0431 Http \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u044d\u0442\u043e \u043b\u044e\u0431\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043a\u0440\u043e\u043c\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0438 middlewares). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c IHttpContextAccessor, \u043d\u043e \u0441\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443. \u041f\u043e \u0442\u043e\u0439 \u0436\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0441\u0438\u0438 \u043f\u043e\u043b\u0435 RequestServiceProvider: \u0445\u043e\u0442\u044f \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0438\u0437 Http \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 IHttpContextAccessor, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u043c\u044b \u043e\u043f\u044f\u0442\u044c \u0443\u043f\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0432 \u0437\u043d\u0430\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445;<\/li>\n<li>\u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c\u0441\u044f \u0441 \u0441\u0435\u0441\u0441\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 ASP.NET (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u0440\u0430\u043d\u0438\u0442 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435), \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 FullState;<\/li>\n<li>\u0442\u0430\u043a \u043a\u0430\u043a \u0432 Http \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u0435\u0440\u0432\u0438\u0441-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f RequestServices, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u0438 \u043c\u044b RequestServiceProvider \u0432 RequestServices, \u0438 \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 SessionServiceProvider \u0432 SessionServices;<\/li>\n<li>\u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043b\u0430\u0441\u0441 FullStateOptions \u043f\u043e\u0434\u043e\u0431\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u0443 SessionOptions, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 \u0440\u0430\u043d\u0435\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u0432\u0448\u0435\u0439\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u0439;<\/li>\n<li>\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f IServiceCollection, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c IMemoryCache, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0449\u0451 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d, IHttpContextAccessor, \u0435\u0441\u043b\u0438 \u0435\u0449\u0451 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c MemoryCacheEntryOptions, \u043e\u0431\u0449\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0435\u0441\u0441\u0438\u0439, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 DI \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 FullState \u043a\u0430\u043a \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IFullState;<\/li>\n<li>\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f IApplicationBuilder, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 middleware;<\/li>\n<li>\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f IServiceProvider, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0441\u0435\u0441\u0441\u0438\u044e \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e IHttpContextAccessor.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public interface IFullState {     IServiceProvider RequestServices { get; }     IServiceProvider SessionServices { get; } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">internal class FullState : IFullState {     public IServiceProvider RequestServices { get; internal set; }      public IServiceProvider SessionServices { get; internal set; } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u043e\u043f\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class FullStateOptions {     public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromHours(1);     public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromSeconds(1);     public CookieBuilder Cookie { get; init; } = new()     {         Name = SessionDefaults.CookieName,         Path = SessionDefaults.CookiePath,         SameSite = SameSiteMode.Lax,         IsEssential = false,         HttpOnly = true,     }; } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public static class FullStateExtensions {      private static readonly FullStateOptions _fullStateOptions = new();     private static MemoryCacheEntryOptions _entryOptions = null!;     private static System.Timers.Timer _checkSessions = null!;     private static int _cookieSequenceGen = 0;      public static IServiceCollection AddFullState(this IServiceCollection services,            Action&lt;FullStateOptions>? configure = null)     {         configure?.Invoke(_fullStateOptions);         if (!services.Any(sd => sd.ServiceType == typeof(IMemoryCache)))         {             services.AddMemoryCache(op =>             {                 op.ExpirationScanFrequency = _fullStateOptions.ExpirationScanFrequency;             });         }         if (!services.Any(sd => sd.ServiceType == typeof(IHttpContextAccessor)))         {             services.AddHttpContextAccessor();         }         _entryOptions = new                MemoryCacheEntryOptions().SetSlidingExpiration(_fullStateOptions.IdleTimeout);         PostEvictionCallbackRegistration postEvictionCallbackRegistration = new                PostEvictionCallbackRegistration();         postEvictionCallbackRegistration.State = typeof(FullStateExtensions);         postEvictionCallbackRegistration.EvictionCallback = (k, v, r, s) =>         {             if (r is EvictionReason.Expired &amp;&amp; s is Type stype &amp;&amp; stype == typeof(FullStateExtensions)                  &amp;&amp; v is IDisposable disposable)             {                 disposable.Dispose();             }         };         _entryOptions.PostEvictionCallbacks.Add(postEvictionCallbackRegistration);          services.AddScoped&lt;IFullState, FullState>();          return services;     }      public static IApplicationBuilder UseFullState(this IApplicationBuilder app)     {         app.Use(async (context, next) =>         {             IMemoryCache sessions = context.RequestServices.GetRequiredService&lt;IMemoryCache>();             if (_checkSessions is null)             {                 lock (app)                 {                     if (_checkSessions is null)                     {                         _checkSessions = new(_fullStateOptions.ExpirationScanFrequency.TotalMilliseconds);                         _checkSessions.Elapsed += (s, e) =>                         {                             sessions.TryGetValue(string.Empty, out object dumb);                         };                         _checkSessions.Enabled = true;                         _checkSessions.AutoReset = true;                     }                 }             }             object? sessionObj = null;             IServiceProvider? session = null!;             string key = context.Request.Cookies[_fullStateOptions.Cookie.Name];             bool isNewSession = false;             FullState fullState = (context.RequestServices.GetRequiredService&lt;IFullState>() as FullState)!;             if (                 key is null                 || !sessions.TryGetValue(key, out sessionObj)                 || (session = sessionObj as IServiceProvider) is null             )             {                 key = $\"{Guid.NewGuid()}:{Interlocked.Increment(ref _cookieSequenceGen)}\";                 session = context.RequestServices.CreateScope().ServiceProvider;                 context.Response.Cookies.Append(_fullStateOptions.Cookie.Name, key, _fullStateOptions.Cookie.Build(context));                 isNewSession = true;             }              fullState.RequestServices = context.RequestServices;             fullState.SessionServices = session!;             try             {                 await (next?.Invoke() ?? Task.CompletedTask);                 if (isNewSession)                 {                     sessions.Set(key, session, _entryOptions);                 }             }             catch (Exception)             {                 throw;             }         });         return app;     }      public static IFullState GetFullState(this IServiceProvider serviceProvider)     {         IHttpContextAccessor ca = serviceProvider.GetRequiredService&lt;IHttpContextAccessor>();         return ca.HttpContext.RequestServices.GetRequiredService&lt;IFullState>();     }  } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/tree\/v2.0.0\/Library\">https:\/\/github.com\/Leksiqq\/FullState\/tree\/v2.0.0\/Library<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u043e\u0432\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">builder.Services.AddFullState(op => {     op.Cookie.Name = \"qq\";     op.ExpirationScanFrequency = TimeSpan.FromSeconds(1);     op.IdleTimeout = TimeSpan.FromSeconds(20); });  builder.Services.AddScoped&lt;InfoProvider>();  builder.Services.AddScoped&lt;Another>();  builder.Logging.ClearProviders(); builder.Logging.AddConsole(op => {     op.TimestampFormat = \"[HH:mm:ss:fff] \"; }); <\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">var app = builder.Build();  app.UseFullState();  app.MapGet(\"\/\", async context => {     Another another = context.RequestServices.GetRequiredService&lt;Another>();     await context.Response.WriteAsync($\"[{DateTime.Now.ToString(\"HH:mm:ss.fff\")}] Hello, World! \"         + $\", controller {another}({another.GetHashCode()}), \"         + context.RequestServices.GetFullState().SessionServices.GetRequiredService&lt;InfoProvider>().Get()); });  app.Run();<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 InfoProvider:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">    public string Get()     {         #region \u0443\u0434\u0430\u043b\u0435\u043d\u043e         \/\/ Session session = _serviceProvider.GetRequiredService&lt;SessionHolder>().Session;        #endregion \u0443\u0434\u0430\u043b\u0435\u043d\u043e         #region \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         IFullState session = _serviceProvider.GetFullState();        #endregion \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e         Another another = session.RequestServices.GetRequiredService&lt;Another>();         _logger.LogInformation($\"{this}({GetHashCode()}) {another}({another.GetHashCode()})\");         List&lt;int> result = new();         while (_queue.TryDequeue(out int k))         {             result.Add(k);         }         return $\"{this}({GetHashCode()}) {another}({another.GetHashCode()}), {string.Join(\", \", result)}\";     }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/v2.0.0\/Tests\/WebApplication1\/Program.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/v2.0.0\/Tests\/WebApplication1\/Program.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/fi\/uc\/qa\/fiucqame68hmzjmqgnvw75x6hme.png\" data-src=\"https:\/\/habrastorage.org\/webt\/fi\/uc\/qa\/fiucqame68hmzjmqgnvw75x6hme.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/w4\/nf\/-i\/w4nf-ife3zu-g-asianqipciw-4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/w4\/nf\/-i\/w4nf-ife3zu-g-asianqipciw-4.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ul\/ph\/7b\/ulph7bfahhz1aqeiflxjbr_p5nk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ul\/ph\/7b\/ulph7bfahhz1aqeiflxjbr_p5nk.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/vq\/kl\/gn\/vqklgnb1uyhxrrsddtyez4gejes.png\" data-src=\"https:\/\/habrastorage.org\/webt\/vq\/kl\/gn\/vqklgnb1uyhxrrsddtyez4gejes.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0440\u0430\u043d\u044c\u0448\u0435, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0432 \u043b\u043e\u0433 \u201cdisposed\u201d \u043e\u0442 \u0441\u0435\u0441\u0441\u0438\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e.<\/p>\n<p>  <\/p>\n<h3 id=\"testirovanie-biblioteki-s-nunit\">\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0441 NUnit<\/h3>\n<p>  <\/p>\n<p>\u041d\u0443 \u0438 \u043d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0447\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043d\u0430\u0434\u043e, \u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 NUnit.<\/p>\n<p>  <\/p>\n<h4 id=\"server\">\u0421\u0435\u0440\u0432\u0435\u0440<\/h4>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 DI \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0442\u0440\u0451\u0445 \u0432\u0440\u0435\u043c\u0451\u043d \u0436\u0438\u0437\u043d\u0438: Transient, Scoped \u0438 Singleton. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u044d\u0442\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0437 \u0442\u0440\u0451\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430 (\u043e\u0434\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u043e\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438 \u0434\u0432\u0443\u0445, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u0438) \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u044f\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u0440\u0435\u043c\u0451\u043d \u0436\u0438\u0437\u043d\u0438, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0433\u043b\u0443\u0431\u0438\u043d\u0430 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0443\u0442\u044c \u043e\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 (\u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0438\u0441\u043f\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0438\u043b\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430). \u042d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 DI:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public interface ITransient {} public interface IScoped {} public interface ISingleton {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043b\u0430\u0441\u0441, \u0447\u044c\u0438 \u043e\u0431\u0435\u043a\u0442\u044b \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class Probe : IDisposable, ITransient, IScoped, ISingleton {     private static int _genId = 0;     private readonly IServiceProvider _services;     private readonly Type[] _types = new[] { typeof(ITransient), typeof(IScoped), typeof(ISingleton) };      internal static int Depth { get; set; } = 4;     public int Id { get; private set; }     public bool IsDisposed { get; private set; } = false;     public Probe(IServiceProvider services)     {         Id = Interlocked.Increment(ref _genId);         _services = services;     }      private void AddTrace(string trace, int value, string? error = null)     {         IFullState session = _services.GetFullState();         session.RequestServices.GetRequiredService&lt;List&lt;TraceItem>>().Add(new TraceItem         {             Trace = trace,             ObjectId = value,             Error = error         });     }      public void DoSomething(string trace)     {         if (!string.IsNullOrEmpty(trace))         {             AddTrace(trace, Id, IsDisposed ? \"disposed\" : null);         }         if (trace.Where(c => c == '\/').Count() &lt; Depth)         {             IFullState session = _services.GetFullState();              IServiceProvider[] services = new[] { _services, session.RequestServices, session.SessionServices };              foreach (Type type in _types)             {                 for (int i = 0; i &lt; services.Length; i++)                 {                     string nextTrace = $\"{trace}\/{type.Name}{i}\";                     try                     {                         Probe probe = (Probe)services[i].GetRequiredService(type);                         probe.DoSomething(nextTrace);                     }                     catch (Exception ex)                     {                         AddTrace(nextTrace, -1, ex.ToString());                     }                 }             }         }      }      public void Dispose()     {         IsDisposed = true;     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u043e\u0441\u0438\u0442\u0435\u043b\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">public class TraceItem {     public int Client { get; set; }     public int Request { get; set; }     public string Session { get; set; }     public string Trace { get; set; }     public int ObjectId { get; set; }     public string? Error { get; set; }      public override string ToString()     {         return $\"{{Client: {Client}, Request: {Request}, Session: {Session}, Trace: {Trace}, ObjectId: {ObjectId}{(Error is { } ? $\", Error: {Error}\" : string.Empty)}}}\";     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"cs\">var builder = WebApplication.CreateBuilder(args);  builder.Services.AddFullState(op => {     op.IdleTimeout = TimeSpan.FromSeconds(20);     op.Cookie.Name = \"qq\"; });  builder.Services.AddScoped&lt;IScoped, Probe>(); builder.Services.AddSingleton&lt;ISingleton, Probe>(); builder.Services.AddTransient&lt;ITransient, Probe>();  builder.Services.AddScoped&lt;List&lt;TraceItem>>();  WebApplication app = builder.Build();  app.UseFullState();  app.MapGet(\"\/\", async (HttpContext context) => {     new Probe(context.RequestServices).DoSomething(string.Empty);      context.RequestServices.GetRequiredService&lt;List&lt;TraceItem>>().ForEach(h => h.Session = context.Request.Cookies[\"qq\"]);      JsonSerializerOptions options = new();      await context.Response.WriteAsJsonAsync(context.RequestServices.GetRequiredService&lt;List&lt;TraceItem>>(), options); });  if(args is { }) {     string url = args.Where(s => s.StartsWith(\"applicationUrl=\")).FirstOrDefault();     if(url is { })     {         app.Urls.Clear();         app.Urls.Add(url.Substring(\"applicationUrl=\".Length));     }     string depth = args.Where(s => s.StartsWith(\"depth=\")).FirstOrDefault();     if(depth is { })     {         Probe.Depth = int.Parse(depth.Substring(\"depth=\".Length));     } }  app.Run(); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 Url \u0438 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430.<\/p>\n<p>  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/tree\/v2.0.0\/Tests\/FullStateTestServer\">https:\/\/github.com\/Leksiqq\/FullState\/tree\/v2.0.0\/Tests\/FullStateTestServer<\/a>.<\/p>\n<p>  <\/p>\n<h4 id=\"testovyy-metod\">\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434<\/h4>\n<p>  <\/p>\n<p>\u0412 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043c\u044b \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0447\u0435\u0440\u0435\u0437 Process, \u0434\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u043d\u0430\u0447\u043d\u0451\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c, \u0438 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432, \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 TraceItem&#8217;\u044b \u043c\u044b \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u043c \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043c\u044b \u0433\u0430\u0441\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c TraceItem&#8217;\u044b. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043e\u0448\u0438\u0431\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c null;<\/li>\n<li>\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u043e\u043c\u0435\u0440 0 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e Session \u0440\u0430\u0432\u043d\u043e null;<\/li>\n<li>\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 > 0 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 Session \u043d\u0435 \u0440\u0430\u0432\u043d\u044b null \u0438 \u0440\u0430\u0432\u043d\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439;<\/li>\n<li>\u0432\u0441\u0435 Singleton \u0440\u0430\u0432\u043d\u044b;<\/li>\n<li>\u0432\u0441\u0435 Transient \u0440\u0430\u0437\u043d\u044b\u0435;<\/li>\n<li>Scoped, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0438\u0437 session.RequestServices, \u0440\u0430\u0432\u043d\u044b \u0432 \u043e\u0434\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b \u0432 \u0440\u0430\u0437\u043d\u044b\u0445;<\/li>\n<li>Scoped, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0438\u0437 session.SessionServices, \u0440\u0430\u0432\u043d\u044b \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432;<\/li>\n<li>Scoped, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0438\u0437 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0432\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u043e\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0431\u043e\u043b\u0435\u0435 \u0445\u0438\u0442\u0440\u043e\u043c\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044e: \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0435\u0433\u043e <em>\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 scope<\/em> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: \u0434\u0432\u0438\u0433\u0430\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0447\u0430\u043b\u0443 \u043f\u0443\u0442\u0438 (\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e Trace, \u0440\u0430\u0437\u0431\u0438\u0442\u043e\u0435 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438, \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \/), \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0439:<br \/> \n<ol>\n<li>\u041e\u0431\u044a\u0435\u043a\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Singleton \u2014 \u0442\u043e\u0433\u0434\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 scope \u2014 Singleton,<\/li>\n<li>\u041e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0438\u0437 session.RequestServices \u0438\u043b\u0438 session.SessionServices \u2014 \u0442\u043e\u0433\u0434\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 scope \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439,<br \/>  \u0435\u0441\u043b\u0438 \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c, \u0442\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 scope \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 session.RequestServices;<\/li>\n<\/ol>\n<\/li>\n<li>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043f\u0438\u0441\u043a\u0430 \u0440\u0430\u0432\u043d\u043e <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/8e3\/0af\/a8f\/8e30afa8f21f06fe0114e3308594f379.svg\" alt=\"$numberOfClients * numberOfRequests * (9^{depth + 1} - 9) \/ 8$\" data-tex=\"inline\"\/>.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0424\u0430\u0439\u043b \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043e\u043d \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u0435\u043b\u0438\u043a, \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d: <a href=\"https:\/\/github.com\/Leksiqq\/FullState\/blob\/v2.0.0\/Tests\/FullStateTestProject\/UnitTest1.cs\">https:\/\/github.com\/Leksiqq\/FullState\/blob\/v2.0.0\/Tests\/FullStateTestProject\/UnitTest1.cs<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0442\u0435\u0441\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7_\/zc\/xz\/7_zcxzzwhp9nz6453sqbt874swk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/7_\/zc\/xz\/7_zcxzzwhp9nz6453sqbt874swk.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/m9\/wm\/qs\/m9wmqsuppzkehwnozj_nfjnlcok.png\" data-src=\"https:\/\/habrastorage.org\/webt\/m9\/wm\/qs\/m9wmqsuppzkehwnozj_nfjnlcok.png\"\/><\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/cloud.timeweb.com\/vds-promo-10-rub?utm_source=habr&amp;utm_medium=banner&amp;utm_campaign=vds-promo-10-rub\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/co\/e2\/kh\/coe2kha8u8_pypip-2k3wk3ppa0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/co\/e2\/kh\/coe2kha8u8_pypip-2k3wk3ppa0.png\"\/><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/666924\/\"> https:\/\/habr.com\/ru\/company\/timeweb\/blog\/666924\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/za\/yk\/yn\/zaykynpiqjdi3vab3e3yv-40wfe.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/za\/yk\/yn\/zaykynpiqjdi3vab3e3yv-40wfe.jpeg\" data-blurred=\"true\"\/><br \/>  \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u0441\u043e\u043e\u0431\u0449\u0443, \u0447\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f Fullstate \u0438 Stateless \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a\u0430\u044f-\u043b\u0438\u0431\u043e \u0430\u0433\u0438\u0442\u0430\u0446\u0438\u044f \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Fullstate. \u041c\u044b \u0438\u0441\u0445\u043e\u0434\u0438\u043c \u0438\u0437 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 ASP.NET \u0434\u043e\u043b\u0436\u0435\u043d \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443.<br \/>  \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u044e \u043c\u043e\u0449\u044c DI-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 .NET!<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-333843","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=333843"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333843\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=333843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=333843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=333843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}