| File: ServiceLookup\DynamicServiceProviderEngine.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj (Microsoft.Extensions.DependencyInjection) |
// 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.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Threading; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal sealed class DynamicServiceProviderEngine : CompiledServiceProviderEngine { private readonly ServiceProvider _serviceProvider; [RequiresDynamicCode("Creates DynamicMethods")] public DynamicServiceProviderEngine(ServiceProvider serviceProvider) : base(serviceProvider) { _serviceProvider = serviceProvider; } public override Func<ServiceProviderEngineScope, object?> RealizeService(ServiceCallSite callSite) { int callCount = 0; return scope => { // Resolve the result before we increment the call count, this ensures that singletons // won't cause any side effects during the compilation of the resolve function. var result = CallSiteRuntimeResolver.Instance.Resolve(callSite, scope); if (Interlocked.Increment(ref callCount) == 2) { // Don't capture the ExecutionContext when forking to build the compiled version of the // resolve function _ = ThreadPool.UnsafeQueueUserWorkItem(_ => { try { _serviceProvider.ReplaceServiceAccessor(callSite, base.RealizeService(callSite)); } catch (Exception ex) { DependencyInjectionEventSource.Log.ServiceRealizationFailed(ex, _serviceProvider.GetHashCode()); Debug.Fail($"We should never get exceptions from the background compilation.{Environment.NewLine}{ex}"); } }, null); } return result; }; } } }