LifetimeDescriptor
Represents a lifetime descriptor.
using Stashbox.Exceptions;
using Stashbox.Expressions;
using Stashbox.Registration.ServiceRegistrations;
using Stashbox.Resolution;
using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace Stashbox.Lifetime
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class LifetimeDescriptor
{
private protected virtual bool StoreResultInLocalVariable => false;
protected virtual int LifeSpan => 0;
protected string Name { get; }
protected LifetimeDescriptor()
{
Name = GetType().Name;
}
[return: System.Runtime.CompilerServices.Nullable(2)]
internal Expression ApplyLifetime(ServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type requestedType)
{
if (resolutionContext.CurrentContainerContext.ContainerConfiguration.LifetimeValidationEnabled && LifeSpan > 0) {
DefaultInterpolatedStringHandler val = default(DefaultInterpolatedStringHandler);
if (resolutionContext.CurrentLifeSpan > LifeSpan) {
Type implementationType = serviceRegistration.ImplementationType;
val..ctor(71, 4);
val.AppendLiteral("The life-span of ");
val.AppendFormatted<Type>(serviceRegistration.ImplementationType);
val.AppendLiteral(" (");
val.AppendFormatted(Name);
val.AppendLiteral("|");
val.AppendFormatted<int>(LifeSpan);
val.AppendLiteral(") ");
val.AppendLiteral("is shorter than its direct or indirect parent's ");
val.AppendFormatted(resolutionContext.NameOfServiceLifeSpanValidatingAgainst);
val.AppendLiteral(".");
throw new LifetimeValidationFailedException(implementationType, val.ToStringAndClear() + Environment.NewLine + "This could lead to incidental lifetime promotions with longer life-span, it's recommended to double check your lifetime configurations.");
}
ResolutionContext resolutionContext2 = resolutionContext;
int lifeSpan = LifeSpan;
val..ctor(4, 3);
val.AppendFormatted<Type>(serviceRegistration.ImplementationType);
val.AppendLiteral(" (");
val.AppendFormatted(Name);
val.AppendLiteral("|");
val.AppendFormatted<int>(LifeSpan);
val.AppendLiteral(")");
resolutionContext = resolutionContext2.BeginLifetimeValidationContext(lifeSpan, val.ToStringAndClear());
}
if (!StoreResultInLocalVariable)
return BuildLifetimeAppliedExpression(serviceRegistration, resolutionContext, requestedType);
ParameterExpression knownVariableOrDefault = resolutionContext.GetKnownVariableOrDefault(serviceRegistration.RegistrationId);
if (knownVariableOrDefault != null)
return knownVariableOrDefault;
Expression expression = BuildLifetimeAppliedExpression(serviceRegistration, resolutionContext, requestedType);
if (expression == null)
return null;
knownVariableOrDefault = requestedType.AsVariable(null);
resolutionContext.AddDefinedVariable(serviceRegistration.RegistrationId, knownVariableOrDefault);
resolutionContext.AddInstruction(knownVariableOrDefault.AssignTo(expression));
return knownVariableOrDefault;
}
[return: System.Runtime.CompilerServices.Nullable(2)]
private protected abstract Expression BuildLifetimeAppliedExpression(ServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type requestedType);
[return: System.Runtime.CompilerServices.Nullable(2)]
private protected static Expression GetExpressionForRegistration(ServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type requestedType)
{
if (!IsRegistrationOutputCacheable(serviceRegistration, resolutionContext))
return ExpressionBuilder.BuildExpressionForRegistration(serviceRegistration, resolutionContext, requestedType);
Expression cachedExpression = resolutionContext.GetCachedExpression(serviceRegistration.RegistrationId);
if (cachedExpression != null)
return cachedExpression;
cachedExpression = ExpressionBuilder.BuildExpressionForRegistration(serviceRegistration, resolutionContext, requestedType);
if (cachedExpression == null)
return null;
resolutionContext.CacheExpression(serviceRegistration.RegistrationId, cachedExpression);
return cachedExpression;
}
private protected static bool IsRegistrationOutputCacheable(ServiceRegistration serviceRegistration, ResolutionContext resolutionContext)
{
if (!serviceRegistration.IsDecorator && resolutionContext.RequestConfiguration.FactoryDelegateCacheEnabled && resolutionContext.PerResolutionRequestCacheEnabled)
return !(serviceRegistration is OpenGenericRegistration);
return false;
}
}
}