ServiceRegistrator
using Stashbox.Lifetime;
using Stashbox.Utils.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Stashbox.Registration
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal static class ServiceRegistrator
{
public static void Register(IContainerContext containerContext, ServiceRegistration serviceRegistration, Type serviceType)
{
if (serviceRegistration.ImplementationType.IsOpenGenericType())
serviceRegistration = new OpenGenericRegistration(serviceRegistration);
PreProcessRegistration(containerContext, serviceRegistration);
if (serviceRegistration.Options.TryGet(RegistrationOption.AdditionalServiceTypes, out object value)) {
ExpandableArray<Type> expandableArray = value as ExpandableArray<Type>;
if (expandableArray != null) {
foreach (Type item in expandableArray.Distinct()) {
if (item.IsOpenGenericType())
RegisterInternal(containerContext, serviceRegistration, item.GetGenericTypeDefinition());
else
RegisterInternal(containerContext, serviceRegistration, item);
}
}
}
RegisterInternal(containerContext, serviceRegistration, serviceType);
}
public static void ReMap(IContainerContext containerContext, ServiceRegistration serviceRegistration, Type serviceType)
{
if (serviceRegistration.ImplementationType.IsOpenGenericType())
serviceRegistration = new OpenGenericRegistration(serviceRegistration);
PreProcessRegistration(containerContext, serviceRegistration);
if (serviceRegistration.Options.TryGet(RegistrationOption.AdditionalServiceTypes, out object value)) {
ExpandableArray<Type> expandableArray = value as ExpandableArray<Type>;
if (expandableArray != null) {
foreach (Type item in expandableArray.Distinct()) {
ReMapInternal(containerContext, serviceRegistration, item);
}
}
}
ReMapInternal(containerContext, serviceRegistration, serviceType);
}
private static void RegisterInternal(IContainerContext containerContext, ServiceRegistration serviceRegistration, Type serviceType)
{
if (serviceRegistration.IsDecorator) {
containerContext.DecoratorRepository.AddDecorator(serviceType, serviceRegistration, false);
containerContext.RootScope.InvalidateDelegateCache();
} else if (containerContext.RegistrationRepository.AddOrUpdateRegistration(serviceRegistration, serviceType)) {
containerContext.RootScope.InvalidateDelegateCache();
}
}
private static void ReMapInternal(IContainerContext containerContext, ServiceRegistration serviceRegistration, Type serviceType)
{
if (serviceRegistration.IsDecorator)
containerContext.DecoratorRepository.AddDecorator(serviceType, serviceRegistration, true);
else
containerContext.RegistrationRepository.AddOrReMapRegistration(serviceRegistration, serviceType);
containerContext.RootScope.InvalidateDelegateCache();
}
private static void PreProcessRegistration(IContainerContext containerContext, ServiceRegistration serviceRegistration)
{
if (serviceRegistration.Options.TryGet(RegistrationOption.RegistrationTypeOptions, out object value)) {
InstanceOptions instanceOptions = value as InstanceOptions;
if (instanceOptions != null) {
PreProcessExistingInstanceIfNeeded(containerContext, instanceOptions.ExistingInstance, serviceRegistration.Options.IsOn(RegistrationOption.IsLifetimeExternallyOwned), serviceRegistration.Options.GetOrDefault<Action<object>>(RegistrationOption.Finalizer), serviceRegistration.ImplementationType);
if (instanceOptions.IsWireUp)
serviceRegistration.Lifetime = Lifetimes.Singleton;
}
}
}
private static void PreProcessExistingInstanceIfNeeded(IContainerContext containerContext, [System.Runtime.CompilerServices.Nullable(2)] object instance, bool isLifetimeExternallyOwned, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<object> finalizer, Type implementationType)
{
if (instance != null) {
if (!isLifetimeExternallyOwned && implementationType.IsDisposable())
containerContext.RootScope.AddDisposableTracking(instance);
if (finalizer != null)
containerContext.RootScope.AddWithFinalizer(instance, finalizer);
}
}
}
}