.net core ServiceProviderEngineScope 源码

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.Extensions.Internal;

namespace Microsoft.Extensions.DependencyInjection.ServiceLookup;

[DebuggerDisplay("{DebuggerToString(),nq}")]
[DebuggerTypeProxy(typeof(ServiceProviderEngineScopeDebugView))]
internal sealed class ServiceProviderEngineScope : IServiceScope, IDisposable, IServiceProvider, IKeyedServiceProvider, IAsyncDisposable, IServiceScopeFactory
{
	private sealed class ServiceProviderEngineScopeDebugView
	{
		private readonly ServiceProviderEngineScope _serviceProvider;

		public List<ServiceDescriptor> ServiceDescriptors => new List<ServiceDescriptor>(_serviceProvider.RootProvider.CallSiteFactory.Descriptors);

		public List<object> Disposables => new List<object>(_serviceProvider.Disposables);

		public bool Disposed => _serviceProvider._disposed;

		public bool IsScope => !_serviceProvider.IsRootScope;

		public ServiceProviderEngineScopeDebugView(ServiceProviderEngineScope serviceProvider)
		{
			_serviceProvider = serviceProvider;
		}
	}

	private bool _disposed;

	private List<object> _disposables;

	internal IList<object> Disposables
	{
		get
		{
			IList<object> disposables = _disposables;
			return disposables ?? Array.Empty<object>();
		}
	}

	internal Dictionary<ServiceCacheKey, object?> ResolvedServices { get; }

	internal bool Disposed => _disposed;

	internal object Sync => ResolvedServices;

	public bool IsRootScope { get; }

	internal ServiceProvider RootProvider { get; }

	public IServiceProvider ServiceProvider => this;

	public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope)
	{
		ResolvedServices = new Dictionary<ServiceCacheKey, object>();
		RootProvider = provider;
		IsRootScope = isRootScope;
	}

	public object? GetService(Type serviceType)
	{
		if (_disposed)
		{
			ThrowHelper.ThrowObjectDisposedException();
		}
		return RootProvider.GetService(ServiceIdentifier.FromServiceType(serviceType), this);
	}

	public object? GetKeyedService(Type serviceType, object? serviceKey)
	{
		if (_disposed)
		{
			ThrowHelper.ThrowObjectDisposedException();
		}
		return RootProvider.GetKeyedService(serviceType, serviceKey, this);
	}

	public object GetRequiredKeyedService(Type serviceType, object? serviceKey)
	{
		if (_disposed)
		{
			ThrowHelper.ThrowObjectDisposedException();
		}
		return RootProvider.GetRequiredKeyedService(serviceType, serviceKey, this);
	}

	public IServiceScope CreateScope()
	{
		return RootProvider.CreateScope();
	}

	[return: NotNullIfNotNull("service")]
	internal object? CaptureDisposable(object? service)
	{
		if (this == service || (!(service is IDisposable) && !(service is IAsyncDisposable)))
		{
			return service;
		}
		bool flag = false;
		lock (Sync)
		{
			if (_disposed)
			{
				flag = true;
			}
			else
			{
				if (_disposables == null)
				{
					_disposables = new List<object>();
				}
				_disposables.Add(service);
			}
		}
		if (flag)
		{
			if (service is IDisposable disposable)
			{
				disposable.Dispose();
			}
			else
			{
				object localService = service;
				Task.Run(() => ((IAsyncDisposable)localService).DisposeAsync().AsTask()).GetAwaiter().GetResult();
			}
			ThrowHelper.ThrowObjectDisposedException();
		}
		return service;
	}

	public void Dispose()
	{
		List<object> list = BeginDispose();
		if (list == null)
		{
			return;
		}
		int num = list.Count - 1;
		while (num >= 0)
		{
			if (list[num] is IDisposable disposable)
			{
				disposable.Dispose();
				num--;
				continue;
			}
			throw new InvalidOperationException(System.SR.Format(System.SR.AsyncDisposableServiceDispose, TypeNameHelper.GetTypeDisplayName(list[num])));
		}
	}

	public ValueTask DisposeAsync()
	{
		List<object> list = BeginDispose();
		if (list != null)
		{
			try
			{
				for (int num = list.Count - 1; num >= 0; num--)
				{
					object obj = list[num];
					if (obj is IAsyncDisposable asyncDisposable)
					{
						ValueTask vt2 = asyncDisposable.DisposeAsync();
						if (!vt2.IsCompletedSuccessfully)
						{
							return Await(num, vt2, list);
						}
						vt2.GetAwaiter().GetResult();
					}
					else
					{
						((IDisposable)obj).Dispose();
					}
				}
			}
			catch (Exception exception)
			{
				return new ValueTask(Task.FromException(exception));
			}
		}
		return default(ValueTask);
		static async ValueTask Await(int i, ValueTask vt, List<object> toDispose)
		{
			await vt.ConfigureAwait(continueOnCapturedContext: false);
			i--;
			while (i >= 0)
			{
				object obj2 = toDispose[i];
				if (obj2 is IAsyncDisposable asyncDisposable2)
				{
					await asyncDisposable2.DisposeAsync().ConfigureAwait(continueOnCapturedContext: false);
				}
				else
				{
					((IDisposable)obj2).Dispose();
				}
				i--;
			}
		}
	}

	private List<object> BeginDispose()
	{
		lock (Sync)
		{
			if (_disposed)
			{
				return null;
			}
			DependencyInjectionEventSource.Log.ScopeDisposed(RootProvider.GetHashCode(), ResolvedServices.Count, _disposables?.Count ?? 0);
			_disposed = true;
		}
		if (IsRootScope && !RootProvider.IsDisposed())
		{
			RootProvider.Dispose();
		}
		return _disposables;
	}

	internal string DebuggerToString()
	{
		string text = $"ServiceDescriptors = {RootProvider.CallSiteFactory.Descriptors.Length}";
		if (!IsRootScope)
		{
			text += ", IsScope = true";
		}
		if (_disposed)
		{
			text += ", Disposed = true";
		}
		return text;
	}
}

  

posted on 2024-08-13 07:56  是水饺不是水饺  阅读(12)  评论(0)    收藏  举报

导航