Improve performance of IsRootScope check (#54555)
authorDavid Fowler <davidfowl@gmail.com>
Tue, 22 Jun 2021 21:07:54 +0000 (14:07 -0700)
committerGitHub <noreply@github.com>
Tue, 22 Jun 2021 21:07:54 +0000 (21:07 +0000)
- Stash a field instead of doing an equality comparison.

Fixes #54351

src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs
src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs
src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs

index 06498ff..4ad8b15 100644 (file)
@@ -16,10 +16,11 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
         private bool _disposed;
         private List<object> _disposables;
 
-        public ServiceProviderEngineScope(ServiceProvider provider)
+        public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope)
         {
             ResolvedServices = new Dictionary<ServiceCacheKey, object>();
             RootProvider = provider;
+            IsRootScope = isRootScope;
         }
 
         internal Dictionary<ServiceCacheKey, object> ResolvedServices { get; }
@@ -29,7 +30,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
         // For other scopes, it protects ResolvedServices and the list of disposables
         internal object Sync => ResolvedServices;
 
-        public bool IsRootScope => this == RootProvider.Root;
+        public bool IsRootScope { get; }
 
         internal ServiceProvider RootProvider { get; }
 
index d21d980..fb7052e 100644 (file)
@@ -36,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
             _createServiceAccessor = CreateServiceAccessor;
             _realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
 
-            Root = new ServiceProviderEngineScope(this);
+            Root = new ServiceProviderEngineScope(this, isRootScope: true);
             CallSiteFactory = new CallSiteFactory(serviceDescriptors);
             // The list of built in services that aren't part of the list of service descriptors
             // keep this in sync with CallSiteFactory.IsService
@@ -173,7 +173,7 @@ namespace Microsoft.Extensions.DependencyInjection
                 ThrowHelper.ThrowObjectDisposedException();
             }
 
-            return new ServiceProviderEngineScope(this);
+            return new ServiceProviderEngineScope(this, isRootScope: false);
         }
 
         private ServiceProviderEngine GetEngine()
index 5c19caa..d43752d 100644 (file)
@@ -12,7 +12,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
         public void DoubleDisposeWorks()
         {
             var provider = new ServiceProvider(new ServiceCollection(), ServiceProviderOptions.Default);
-            var serviceProviderEngineScope = new ServiceProviderEngineScope(provider);
+            var serviceProviderEngineScope = new ServiceProviderEngineScope(provider, isRootScope: true);
             serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
             serviceProviderEngineScope.Dispose();
             serviceProviderEngineScope.Dispose();