Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.5.1-preview-623" />

 LazyResolver

using Stashbox.Utils; using Stashbox.Utils.Data; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Stashbox.Resolution.Resolvers { internal class LazyResolver : IEnumerableSupportedResolver, IResolver { private static readonly MethodInfo ResolveMethodInfo = Constants.ResolverType.GetMethodByArguments("Resolve", typeof(Type), Constants.ObjectType, typeof(bool), typeof(object[])); public Expression GetExpression(IResolutionStrategy resolutionStrategy, TypeInformation typeInfo, ResolutionContext resolutionContext) { TypeInformation typeInformation = typeInfo.CloneForType(typeInfo.Type.GetGenericArguments()[0]); Type type = Constants.FuncType.MakeGenericType(typeInformation.Type); ConstructorInfo constructor = typeInfo.Type.GetConstructor(type); Expression lazyFuncExpression = GetLazyFuncExpression(typeInformation, resolutionContext, resolutionStrategy); if (lazyFuncExpression != null) return constructor.MakeNew(lazyFuncExpression.AsLambda(Array.Empty<ParameterExpression>())); return null; } public IEnumerable<Expression> GetExpressionsForEnumerableRequest(IResolutionStrategy resolutionStrategy, TypeInformation typeInfo, ResolutionContext resolutionContext) { TypeInformation typeInformation = typeInfo.CloneForType(typeInfo.Type.GetGenericArguments()[0]); Type type = Constants.FuncType.MakeGenericType(typeInformation.Type); ConstructorInfo lazyConstructor = typeInfo.Type.GetConstructor(type); IEnumerable<Expression> enumerable = resolutionStrategy.BuildExpressionsForEnumerableRequest(resolutionContext, typeInformation); if (enumerable == null) return null; return from e in enumerable select lazyConstructor.MakeNew(e.AsLambda(Array.Empty<ParameterExpression>())); } public bool CanUseForResolution(TypeInformation typeInfo, ResolutionContext resolutionContext) { if (typeInfo.Type.IsClosedGenericType()) return typeInfo.Type.GetGenericTypeDefinition() == typeof(Lazy<>); return false; } private Expression GetLazyFuncExpression(TypeInformation argumentType, ResolutionContext resolutionContext, IResolutionStrategy resolutionStrategy) { if (!resolutionContext.CurrentContainerContext.ContainerConfiguration.CircularDependenciesWithLazyEnabled) return resolutionStrategy.BuildExpressionForType(resolutionContext, argumentType); return resolutionContext.CurrentScopeParameter.CallMethod(ResolveMethodInfo, argumentType.Type.AsConstant(), argumentType.DependencyName.AsConstant(), false.AsConstant(), Constants.ObjectType.InitNewArray(resolutionContext.ParameterExpressions.SelectMany((Pair<bool, ParameterExpression>[] x) => from i in x select i.I2.ConvertTo(Constants.ObjectType)))).ConvertTo(argumentType.Type); } } }