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;
}
}
}