From 306042bbfd4f4ccaa617f5a1d154a5d605d0a215 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 25 Jun 2021 01:20:48 -0700 Subject: [PATCH] Clean up some DI code - Remove empty CreateInstanceCallSite file - Removed ServiceScopeFactoryCallsite and used ConstantCallsite instead. - Added fast path if the value is already cached on the callsite. --- .../src/CallSiteJsonFormatter.cs | 5 ----- .../src/ServiceLookup/CallSiteKind.cs | 4 ---- .../ServiceLookup/CallSiteRuntimeResolver.cs | 11 ++++++----- .../src/ServiceLookup/CallSiteValidator.cs | 4 +--- .../src/ServiceLookup/CallSiteVisitor.cs | 5 ----- .../src/ServiceLookup/ConstantCallSite.cs | 2 +- .../ServiceLookup/CreateInstanceCallSite.cs | 9 --------- .../Expressions/ExpressionResolverBuilder.cs | 5 ----- .../ILEmit/ILEmitResolverBuilder.cs | 6 ------ .../ServiceScopeFactoryCallSite.cs | 19 ------------------- .../src/ServiceProvider.cs | 2 +- 11 files changed, 9 insertions(+), 63 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CreateInstanceCallSite.cs delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceScopeFactoryCallSite.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs index a853a9fe5b590..a2b3d5f095244 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs @@ -81,11 +81,6 @@ protected override object VisitServiceProvider(ServiceProviderCallSite servicePr return null; } - protected override object VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, CallSiteFormatterContext argument) - { - return null; - } - protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("itemType", enumerableCallSite.ItemType); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteKind.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteKind.cs index 83ba197ad888c..112e9afc8fccd 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteKind.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteKind.cs @@ -19,10 +19,6 @@ internal enum CallSiteKind Transient, - CreateInstance, - - ServiceScopeFactory, - Singleton } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs index e7ddb41fb0824..fabaea9fbe7eb 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteRuntimeResolver.cs @@ -20,6 +20,12 @@ private CallSiteRuntimeResolver() public object Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) { + // Fast path to avoid virtual calls if we already have the cached value in the root scope + if (scope.IsRootScope && callSite.Value is object cached) + { + return cached; + } + return VisitCallSite(callSite, new RuntimeResolverContext { Scope = scope @@ -153,11 +159,6 @@ protected override object VisitServiceProvider(ServiceProviderCallSite servicePr return context.Scope; } - protected override object VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, RuntimeResolverContext context) - { - return serviceScopeFactoryCallSite.Value; - } - protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) { var array = Array.CreateInstance( diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs index f836ba78b41b3..29a95f507d357 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs @@ -78,7 +78,7 @@ protected override Type VisitRootCache(ServiceCallSite singletonCallSite, CallSi protected override Type VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state) { // We are fine with having ServiceScopeService requested by singletons - if (scopedCallSite is ServiceScopeFactoryCallSite) + if (scopedCallSite.ServiceType == typeof(IServiceScopeFactory)) { return null; } @@ -100,8 +100,6 @@ protected override Type VisitScopeCache(ServiceCallSite scopedCallSite, CallSite protected override Type VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteValidatorState state) => null; - protected override Type VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, CallSiteValidatorState state) => null; - protected override Type VisitFactory(FactoryCallSite factoryCallSite, CallSiteValidatorState state) => null; internal struct CallSiteValidatorState diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteVisitor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteVisitor.cs index 5308501c89d6e..b7143a2c577fc 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteVisitor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteVisitor.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Runtime.CompilerServices; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { @@ -51,8 +50,6 @@ protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument return VisitConstant((ConstantCallSite)callSite, argument); case CallSiteKind.ServiceProvider: return VisitServiceProvider((ServiceProviderCallSite)callSite, argument); - case CallSiteKind.ServiceScopeFactory: - return VisitServiceScopeFactory((ServiceScopeFactoryCallSite)callSite, argument); default: throw new NotSupportedException(SR.Format(SR.CallSiteTypeNotSupported, callSite.GetType())); } @@ -84,8 +81,6 @@ protected virtual TResult VisitScopeCache(ServiceCallSite callSite, TArgument ar protected abstract TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument); - protected abstract TResult VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, TArgument argument); - protected abstract TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument); protected abstract TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs index a27cb110389d3..bb822437a0e36 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs @@ -21,7 +21,7 @@ public ConstantCallSite(Type serviceType, object defaultValue): base(ResultCache Value = defaultValue; } - public override Type ServiceType => DefaultValue?.GetType() ?? _serviceType; + public override Type ServiceType => _serviceType; public override Type ImplementationType => DefaultValue?.GetType() ?? _serviceType; public override CallSiteKind Kind { get; } = CallSiteKind.Constant; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CreateInstanceCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CreateInstanceCallSite.cs deleted file mode 100644 index 6532a5a7728c7..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CreateInstanceCallSite.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.ExceptionServices; - -namespace Microsoft.Extensions.DependencyInjection.ServiceLookup -{ -} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs index 07ff50a44d671..76e54ec281447 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs @@ -117,11 +117,6 @@ protected override Expression VisitServiceProvider(ServiceProviderCallSite servi return ScopeParameter; } - protected override Expression VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, object context) - { - return Expression.Constant(serviceScopeFactoryCallSite.Value); - } - protected override Expression VisitFactory(FactoryCallSite factoryCallSite, object context) { return Expression.Invoke(Expression.Constant(factoryCallSite.Factory), ScopeParameter); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs index a9015e12a99f0..61690bdd45139 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs @@ -194,12 +194,6 @@ protected override object VisitServiceProvider(ServiceProviderCallSite servicePr return null; } - protected override object VisitServiceScopeFactory(ServiceScopeFactoryCallSite serviceScopeFactoryCallSite, ILEmitResolverBuilderContext argument) - { - AddConstant(argument, serviceScopeFactoryCallSite.Value); - return null; - } - protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ILEmitResolverBuilderContext argument) { if (enumerableCallSite.ServiceCallSites.Length == 0) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceScopeFactoryCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceScopeFactoryCallSite.cs deleted file mode 100644 index 116c6037cab7d..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceScopeFactoryCallSite.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; - -namespace Microsoft.Extensions.DependencyInjection.ServiceLookup -{ - internal sealed class ServiceScopeFactoryCallSite : ServiceCallSite - { - public ServiceScopeFactoryCallSite(IServiceScopeFactory value) : base(ResultCache.None) - { - Value = value; - } - - public override Type ServiceType { get; } = typeof(IServiceScopeFactory); - public override Type ImplementationType { get; } = typeof(ServiceProviderEngine); - public override CallSiteKind Kind { get; } = CallSiteKind.ServiceScopeFactory; - } -} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index fb7052ec8ea66..b93a11d956619 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -41,7 +41,7 @@ internal ServiceProvider(IEnumerable serviceDescriptors, Serv // The list of built in services that aren't part of the list of service descriptors // keep this in sync with CallSiteFactory.IsService CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite()); - CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite(Root)); + CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root)); CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory)); if (options.ValidateScopes)