Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="2.8.9-preview-513" />

 RegistrationRepository

using Stashbox.Configuration; using Stashbox.Entity; using Stashbox.Registration.Extensions; using Stashbox.Resolution; using Stashbox.Utils; using System; using System.Collections.Generic; using System.Linq; namespace Stashbox.Registration { internal class RegistrationRepository : IRegistrationRepository { private readonly ContainerConfiguration containerConfiguration; private AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> serviceRepository = AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>>.Empty; private AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> namedScopeRepository = AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>>.Empty; public RegistrationRepository(ContainerConfiguration containerConfiguration) { this.containerConfiguration = containerConfiguration; } public void AddOrUpdateRegistration(IServiceRegistration registration, Type serviceType, bool remap, bool replace) { if (registration.HasScopeName) AddOrUpdateRegistration(ref namedScopeRepository, registration, serviceType, remap, replace); else AddOrUpdateRegistration(ref serviceRepository, registration, serviceType, remap, replace); } private void AddOrUpdateRegistration(ref AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> repository, IServiceRegistration registration, Type serviceType, bool remap, bool replace) { ArrayStoreKeyed<object, IServiceRegistration> arrayStoreKeyed = new ArrayStoreKeyed<object, IServiceRegistration>(registration.RegistrationId, registration); if (remap) Swap.SwapValue<Type, ArrayStoreKeyed<object, IServiceRegistration>, byte, byte, AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>>>(ref repository, (Type t1, ArrayStoreKeyed<object, IServiceRegistration> t2, byte t3, byte t4, AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> repo) => repo.AddOrUpdate(t1, t2, true), serviceType, arrayStoreKeyed, 0, 0); else Swap.SwapValue(ref repository, (IServiceRegistration t1, Type t2, ArrayStoreKeyed<object, IServiceRegistration> t3, bool t4, AvlTreeKeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> repo) => repo.AddOrUpdate(t2, t3, (ArrayStoreKeyed<object, IServiceRegistration> oldValue, ArrayStoreKeyed<object, IServiceRegistration> newValue) => oldValue.AddOrUpdate(t1.RegistrationId, t1, t4)), registration, serviceType, arrayStoreKeyed, replace); } public IServiceRegistration GetRegistrationOrDefault(Type type, ResolutionContext resolutionContext, object name = null) { if (name == null) return GetDefaultRegistrationOrDefault(type, resolutionContext); return GetNamedRegistrationOrDefault(type, name, resolutionContext); } public IServiceRegistration GetRegistrationOrDefault(TypeInformation typeInfo, ResolutionContext resolutionContext) { if (typeInfo.DependencyName == null) return GetDefaultRegistrationOrDefault(typeInfo, resolutionContext); return GetNamedRegistrationOrDefault(typeInfo, resolutionContext); } public IEnumerable<KeyValue<object, IServiceRegistration>> GetRegistrationsOrDefault(Type type, ResolutionContext resolutionContext) { if (resolutionContext.ScopeNames == null) return GetAllRegistrationsOrDefault(type); return GetAllScopedRegistrationsOrDefault(type, resolutionContext) ?? GetAllRegistrationsOrDefault(type); } public IEnumerable<KeyValuePair<Type, IServiceRegistration>> GetRegistrationMappings() { return serviceRepository.Walk().SelectMany((KeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> reg) => from r in reg.Value select new KeyValuePair<Type, IServiceRegistration>(reg.Key, r)).Concat(namedScopeRepository.Walk().SelectMany((KeyValue<Type, ArrayStoreKeyed<object, IServiceRegistration>> reg) => from r in reg.Value select new KeyValuePair<Type, IServiceRegistration>(reg.Key, r))); } public bool ContainsRegistration(Type type, object name) { if (!serviceRepository.ContainsRegistration(type, name)) return namedScopeRepository.ContainsRegistration(type, name); return true; } private IServiceRegistration GetNamedRegistrationOrDefault(Type type, object dependencyName, ResolutionContext resolutionContext) { if (resolutionContext.ScopeNames == null) return GetDefaultRegistrationsOrDefault(type)?.GetOrDefault(dependencyName); object obj = GetScopedRegistrationsOrDefault(type, resolutionContext)?.GetOrDefault(dependencyName); if (obj == null) { ArrayStoreKeyed<object, IServiceRegistration> defaultRegistrationsOrDefault = GetDefaultRegistrationsOrDefault(type); if (defaultRegistrationsOrDefault == null) return null; obj = defaultRegistrationsOrDefault.GetOrDefault(dependencyName); } return (IServiceRegistration)obj; } private IServiceRegistration GetNamedRegistrationOrDefault(TypeInformation typeInfo, ResolutionContext resolutionContext) { if (resolutionContext.ScopeNames == null) { ArrayStoreKeyed<object, IServiceRegistration> defaultRegistrationsOrDefault = GetDefaultRegistrationsOrDefault(typeInfo.Type); if (!containerConfiguration.TreatingParameterAndMemberNameAsDependencyNameEnabled) return defaultRegistrationsOrDefault?.GetOrDefault(typeInfo.DependencyName); return defaultRegistrationsOrDefault?.GetOrDefault(typeInfo.DependencyName) ?? GetDefaultRegistrationOrDefault(typeInfo, resolutionContext); } if (!containerConfiguration.TreatingParameterAndMemberNameAsDependencyNameEnabled) { object obj = GetScopedRegistrationsOrDefault(typeInfo.Type, resolutionContext)?.GetOrDefault(typeInfo.DependencyName); if (obj == null) { ArrayStoreKeyed<object, IServiceRegistration> defaultRegistrationsOrDefault2 = GetDefaultRegistrationsOrDefault(typeInfo.Type); if (defaultRegistrationsOrDefault2 == null) return null; obj = defaultRegistrationsOrDefault2.GetOrDefault(typeInfo.DependencyName); } return (IServiceRegistration)obj; } ArrayStoreKeyed<object, IServiceRegistration> scopedRegistrationsOrDefault = GetScopedRegistrationsOrDefault(typeInfo.Type, resolutionContext); if (scopedRegistrationsOrDefault == null) return GetDefaultRegistrationsOrDefault(typeInfo.Type)?.GetOrDefault(typeInfo.DependencyName) ?? GetDefaultRegistrationOrDefault(typeInfo, resolutionContext); return scopedRegistrationsOrDefault.GetOrDefault(typeInfo.DependencyName) ?? GetDefaultRegistrationOrDefault(typeInfo, resolutionContext); } private IServiceRegistration GetDefaultRegistrationOrDefault(TypeInformation typeInfo, ResolutionContext resolutionContext) { ArrayStoreKeyed<object, IServiceRegistration> defaultOrScopedRegistrationsOrDefault = GetDefaultOrScopedRegistrationsOrDefault(typeInfo.Type, resolutionContext); if (defaultOrScopedRegistrationsOrDefault == null) return null; if (defaultOrScopedRegistrationsOrDefault.Length == 1 && defaultOrScopedRegistrationsOrDefault.Last.IsResolvableByUnnamedRequest) return defaultOrScopedRegistrationsOrDefault.Last; IEnumerable<IServiceRegistration> source = from reg in defaultOrScopedRegistrationsOrDefault where reg.HasCondition select reg; object obj; if (!typeInfo.Type.IsClosedGenericType()) { obj = source.LastOrDefault(delegate(IServiceRegistration reg) { if (reg.IsUsableForCurrentContext(typeInfo)) return reg.IsResolvableByUnnamedRequest; return false; }); if (obj == null) return defaultOrScopedRegistrationsOrDefault.LastOrDefault((IServiceRegistration reg) => reg.IsResolvableByUnnamedRequest); } else obj = (source.LastOrDefault(delegate(IServiceRegistration reg) { if (reg.ValidateGenericConstraints(typeInfo.Type) && reg.IsUsableForCurrentContext(typeInfo)) return reg.IsResolvableByUnnamedRequest; return false; }) ?? defaultOrScopedRegistrationsOrDefault.LastOrDefault(delegate(IServiceRegistration reg) { if (reg.ValidateGenericConstraints(typeInfo.Type)) return reg.IsResolvableByUnnamedRequest; return false; })); return (IServiceRegistration)obj; } private IServiceRegistration GetDefaultRegistrationOrDefault(Type type, ResolutionContext resolutionContext) { ArrayStoreKeyed<object, IServiceRegistration> defaultOrScopedRegistrationsOrDefault = GetDefaultOrScopedRegistrationsOrDefault(type, resolutionContext); if (defaultOrScopedRegistrationsOrDefault == null) return null; if (defaultOrScopedRegistrationsOrDefault.Length == 1 && defaultOrScopedRegistrationsOrDefault.Last.IsResolvableByUnnamedRequest) return defaultOrScopedRegistrationsOrDefault.Last; if (!type.IsClosedGenericType()) return defaultOrScopedRegistrationsOrDefault.LastOrDefault((IServiceRegistration reg) => reg.IsResolvableByUnnamedRequest); return defaultOrScopedRegistrationsOrDefault.LastOrDefault(delegate(IServiceRegistration reg) { if (reg.ValidateGenericConstraints(type)) return reg.IsResolvableByUnnamedRequest; return false; }); } private ArrayStoreKeyed<object, IServiceRegistration> GetDefaultOrScopedRegistrationsOrDefault(Type type, ResolutionContext resolutionContext) { if (resolutionContext.ScopeNames == null) return GetDefaultRegistrationsOrDefault(type); return GetScopedRegistrationsOrDefault(type, resolutionContext) ?? GetDefaultRegistrationsOrDefault(type); } private ArrayStoreKeyed<object, IServiceRegistration> GetDefaultRegistrationsOrDefault(Type type) { ArrayStoreKeyed<object, IServiceRegistration> orDefault = serviceRepository.GetOrDefault(type); if (orDefault == null && type.IsClosedGenericType()) return serviceRepository.GetOrDefault(type.GetGenericTypeDefinition()); return orDefault; } private ArrayStoreKeyed<object, IServiceRegistration> GetScopedRegistrationsOrDefault(Type type, ResolutionContext resolutionContext) { ArrayStoreKeyed<object, IServiceRegistration> arrayStoreKeyed = namedScopeRepository.GetOrDefault(type)?.WhereOrDefault((KeyValue<object, IServiceRegistration> kv) => kv.Value.CanInjectIntoNamedScope(resolutionContext.ScopeNames)); if (arrayStoreKeyed == null && type.IsClosedGenericType()) return namedScopeRepository.GetOrDefault(type.GetGenericTypeDefinition())?.WhereOrDefault((KeyValue<object, IServiceRegistration> kv) => kv.Value.CanInjectIntoNamedScope(resolutionContext.ScopeNames)); return arrayStoreKeyed; } private IEnumerable<KeyValue<object, IServiceRegistration>> GetAllRegistrationsOrDefault(Type type) { ArrayStoreKeyed<object, IServiceRegistration> orDefault = serviceRepository.GetOrDefault(type); if (!type.IsClosedGenericType()) { if (orDefault == null) return null; return orDefault.Repository; } ArrayStoreKeyed<object, IServiceRegistration> orDefault2 = serviceRepository.GetOrDefault(type.GetGenericTypeDefinition()); object enumerable2; if (orDefault2 != null) { IEnumerable<KeyValue<object, IServiceRegistration>> enumerable = (orDefault != null) ? (from reg in orDefault.Repository.Concat(from reg in orDefault2.Repository where reg.Value.ValidateGenericConstraints(type) select reg) orderby reg.Value.RegistrationNumber select reg) : null; enumerable2 = enumerable; if (enumerable2 == null) return from reg in orDefault2.Repository where reg.Value.ValidateGenericConstraints(type) select reg; } else { IEnumerable<KeyValue<object, IServiceRegistration>> enumerable = (orDefault != null) ? orDefault.Repository : null; enumerable2 = enumerable; } return (IEnumerable<KeyValue<object, IServiceRegistration>>)enumerable2; } private IEnumerable<KeyValue<object, IServiceRegistration>> GetAllScopedRegistrationsOrDefault(Type type, ResolutionContext resolutionContext) { ArrayStoreKeyed<object, IServiceRegistration> arrayStoreKeyed = namedScopeRepository.GetOrDefault(type)?.WhereOrDefault((KeyValue<object, IServiceRegistration> kv) => kv.Value.CanInjectIntoNamedScope(resolutionContext.ScopeNames)); if (!type.IsClosedGenericType()) { if (arrayStoreKeyed == null) return null; return arrayStoreKeyed.Repository; } ArrayStoreKeyed<object, IServiceRegistration> arrayStoreKeyed2 = namedScopeRepository.GetOrDefault(type.GetGenericTypeDefinition())?.WhereOrDefault((KeyValue<object, IServiceRegistration> kv) => kv.Value.CanInjectIntoNamedScope(resolutionContext.ScopeNames)); object enumerable2; if (arrayStoreKeyed2 != null) { IEnumerable<KeyValue<object, IServiceRegistration>> enumerable = (arrayStoreKeyed != null) ? (from reg in arrayStoreKeyed.Repository.Concat(from reg in arrayStoreKeyed2.Repository where reg.Value.ValidateGenericConstraints(type) select reg) orderby reg.Value.RegistrationNumber select reg) : null; enumerable2 = enumerable; if (enumerable2 == null) return from reg in arrayStoreKeyed2.Repository where reg.Value.ValidateGenericConstraints(type) select reg; } else { IEnumerable<KeyValue<object, IServiceRegistration>> enumerable = (arrayStoreKeyed != null) ? arrayStoreKeyed.Repository : null; enumerable2 = enumerable; } return (IEnumerable<KeyValue<object, IServiceRegistration>>)enumerable2; } } }