Exemple #1
0
        public ResolveExpressionContext(TypeKey requestedTypeKey,
                                        Registration registration,
                                        DependencyOverrides dependencyOverrides,
                                        DependencyInjectionContainer container)
        {
            RequestedTypeKey                    = requestedTypeKey.MustNotBeEmpty(nameof(requestedTypeKey));
            Registration                        = registration.MustNotBeNull(nameof(registration));
            DependencyOverrides                 = dependencyOverrides;
            Container                           = container.MustNotBeNull(nameof(container));
            RegistrationTypeInfo                = registration.TypeKey.Type.GetTypeInfo();
            ResolvedGenericRegistrationType     = null;
            ResolvedGenericRegistrationTypeInfo = null;

            // ReSharper disable once PossibleNullReferenceException
            if (RegistrationTypeInfo.IsGenericTypeDefinition == false)
            {
                return;
            }

            try
            {
                ResolvedGenericRegistrationType     = registration.TargetType.MakeGenericType(RequestedType.GenericTypeArguments);
                ResolvedGenericRegistrationTypeInfo = ResolvedGenericRegistrationType.GetTypeInfo();
            }
            catch (Exception exception)
            {
                throw new ResolveException($"Could not resolve a concrete instance of the generic type definition \"{RegistrationType}\" using the type \"{RequestedType}\".", exception);
            }
        }
 public ResolveContext ChangeInitialContext(DependencyInjectionContainer container, DependencyOverrides dependencyOverrides)
 {
     _registration   = null;
     _createInstance = null;
     _perResolveInstances?.Clear();
     _container           = container.MustNotBeNull(nameof(container));
     _dependencyOverrides = dependencyOverrides;
     return(this);
 }
Exemple #3
0
        public ResolveDelegate Create(Registration registration, DependencyOverrides dependencyOverrides, DependencyInjectionContainer container)
        {
            registration.MustNotBeNull(nameof(registration));
            container.MustNotBeNull(nameof(container));

            var resolveExpression = CreateResolveExpressionRecursively(registration.TypeKey, registration, dependencyOverrides, container);

            return(resolveExpression.CompileToResolveDelegate(Constants.ResolveContextParameterExpression));
        }
Exemple #4
0
        public ResolveDelegate Create(TypeKey typeKey, DependencyOverrides dependencyOverrides, DependencyInjectionContainer container)
        {
            typeKey.MustNotBeEmpty(nameof(typeKey));
            container.MustNotBeNull(nameof(container));

            var resolveExpression = CreateResolveExpressionRecursively(typeKey, container, dependencyOverrides);

            return(resolveExpression.CompileToResolveDelegate(Constants.ResolveContextParameterExpression));
        }
 public ResolveContext(DependencyInjectionContainer container, DependencyOverrides dependencyOverrides)
 {
     _container           = container.MustNotBeNull(nameof(container));
     _dependencyOverrides = dependencyOverrides;
 }
Exemple #6
0
        private Expression CreateResolveExpressionRecursively(TypeKey requestedTypeKey, Registration registration, DependencyOverrides dependencyOverrides, DependencyInjectionContainer container)
        {
            // Check if the lifetime of the registration would need to create a new instance.
            // If not, then we do not need to create a construction expression
            Expression resolveContextExpression;

            if (registration.Lifetime.IsCreatingNewInstances == false)
            {
                // If the lifetime can be resolved during compilation, then create a resolve context and immediately
                // call ResolveInstance to compile a constant reference to the instance into the resolve method
                if (registration.Lifetime.CanBeResolvedDuringCompilation)
                {
                    var instance = registration.Lifetime.ResolveInstance(container.Services.ResolveContextFactory.Create(container).ChangeRegistration(registration));
                    return(Expression.Constant(instance, requestedTypeKey.Type));
                }

                // Else prepare the resolve context parameter with the target registration and call the ResolveInstance dynamically
                resolveContextExpression = Expression.Call(Constants.ResolveContextParameterExpression,
                                                           Constants.ChangeRegistrationMethod,
                                                           Expression.Constant(registration));
                return(Expression.Convert(Expression.Call(Expression.Constant(registration.Lifetime),
                                                          Constants.LifetimeResolveInstanceMethod,
                                                          resolveContextExpression),
                                          requestedTypeKey.Type));
            }

            // Else we need to create a construction expression that instantiates the target type and performs any instance manipulations
            var resolveExpressionContext = new ResolveExpressionContext(requestedTypeKey, registration, dependencyOverrides, container);
            var constructionExpression   = CreateConstructionExpression(resolveExpressionContext);

            // Check if the lifetime implements IOptimizeLifetimeExpression to avoid compiling the construction expression to a delegate
            if (registration.Lifetime is IOptimizeLifetimeExpression optimizeLifetimeExpression)
            {
                return(optimizeLifetimeExpression.Optimize(constructionExpression, resolveExpressionContext));
            }

            // Compile the construction expression to a delegate so that it can be injected into the ResolveContext
            var compiledDelegate = constructionExpression.CompileToResolveDelegate(Constants.ResolveContextParameterExpression);

            var targetLifetime = resolveExpressionContext.IsResolvingGenericTypeDefinition ? registration.Lifetime.GetLifetimeInstanceForConstructedGenericType() : registration.Lifetime;

            // If the lifetime can be resolved during compilation, then create a resolve context and immediately
            // call ResolveInstance to compile a constant reference to the instance into the resolve method
            if (targetLifetime.CanBeResolvedDuringCompilation)
            {
                var instance = targetLifetime.ResolveInstance(container.Services.ResolveContextFactory.Create(container).ChangeResolvedType(registration, compiledDelegate));
                return(Expression.Constant(instance));
            }

            // Else create a expression that calls the target lifetime using the compiled delegate
            resolveContextExpression = Expression.Call(Constants.ResolveContextParameterExpression,
                                                       Constants.ChangeResolvedTypeMethod,
                                                       Expression.Constant(registration),
                                                       Expression.Constant(compiledDelegate));
            return(Expression.Convert(Expression.Call(Expression.Constant(targetLifetime),
                                                      Constants.LifetimeResolveInstanceMethod,
                                                      resolveContextExpression),
                                      requestedTypeKey.Type));
        }
Exemple #7
0
        private Expression CreateResolveExpressionRecursively(TypeKey requestedTypeKey, DependencyInjectionContainer container, DependencyOverrides dependencyOverrides, bool?tryResolveAll = null)
        {
            // Check if the instance is overridden
            if (dependencyOverrides?.HasOverriddenInstance(requestedTypeKey) == true)
            {
                return(Expression.Convert(Expression.Call(Expression.Call(Constants.ResolveContextParameterExpression, Constants.GetDependencyOverridesProperty),
                                                          Constants.GetOverriddenInstanceMethod,
                                                          Expression.Constant(requestedTypeKey)),
                                          requestedTypeKey.Type));
            }

            // Else ask the container for a ResolveInfo to identify how the returned expression should be composed
            var resolveInfo = container.GetResolveInfo(requestedTypeKey, tryResolveAll);

            if (resolveInfo is ResolveRegistrationInfo resolveRegistrationInfo)
            {
                return(CreateResolveExpressionRecursively(requestedTypeKey, resolveRegistrationInfo.Registration, dependencyOverrides, container));
            }
            if (resolveInfo is ResolveAllInfo resolveAllInfo)
            {
                return(CreateResolveAllExpressionRecursively(resolveAllInfo, dependencyOverrides, container));
            }

            throw new InvalidOperationException($"Cannot handle ResolveInfo \"{resolveInfo}\" in this current implementation of \"{nameof(CompiledLinqExpressionFactory)}\"");
        }
Exemple #8
0
        private Expression CreateResolveAllExpressionRecursively(ResolveAllInfo resolveAllInfo, DependencyOverrides dependencyOverrides, DependencyInjectionContainer container)
        {
            // Create the expression that instantiates the target collection
            var collectionRegistration = container.GetRegistration(resolveAllInfo.CollectionType);

            if (collectionRegistration == null)
            {
                throw new ResolveException($"There is no registration present to resolve collection type \"{resolveAllInfo.CollectionType}\".");
            }
            var createCollectionExpression = CreateConstructionExpression(new ResolveExpressionContext(new TypeKey(resolveAllInfo.CollectionType), collectionRegistration, dependencyOverrides, container));

            // Create the expression block that assigns the created collection to a variable, casts this variable to IList<TargetType>, and then resolves all registrations, adding the resulting the expressions
            var blockExpressions         = new Expression[resolveAllInfo.Registrations.Count + 3]; // +3 for initial assignment, casting to IList<ItemType>, and return statement
            var variableExpression       = Expression.Variable(resolveAllInfo.CollectionType);
            var assignVariableExpression = Expression.Assign(variableExpression, createCollectionExpression);

            blockExpressions[0] = assignVariableExpression; // Assign created collection to variable
            var closedConstructedICollectionType    = Constants.ICollectionGenericTypeDefinition.MakeGenericType(resolveAllInfo.ItemType);
            var castedICollectionVariableExpression = Expression.Variable(closedConstructedICollectionType);
            var assignCastedListExpression          = Expression.Assign(castedICollectionVariableExpression, Expression.ConvertChecked(variableExpression, closedConstructedICollectionType));

            blockExpressions[1] = assignCastedListExpression; // Assign casted list to variable

            // Resolve all registrations and add them to the collection
            var addMethodInfo = closedConstructedICollectionType.GetRuntimeMethod("Add", new[] { resolveAllInfo.ItemType });

            for (var i = 0; i < resolveAllInfo.Registrations.Count; i++)
            {
                var registration = resolveAllInfo.Registrations[i];
                var itemTypeKey  = new TypeKey(resolveAllInfo.ItemType, registration.RegistrationName);
                var resolveRegistrationExpression = CreateResolveExpressionRecursively(itemTypeKey, registration, dependencyOverrides, container);
                blockExpressions[i + 2] = Expression.Call(castedICollectionVariableExpression, addMethodInfo, resolveRegistrationExpression);
            }

            blockExpressions[blockExpressions.Length - 1] = variableExpression; // Return statement

            return(Expression.Block(resolveAllInfo.CollectionType, new[] { variableExpression, castedICollectionVariableExpression }, blockExpressions));
        }
 public ResolveDelegateId(TypeKey typeKey, DependencyOverrides overrides = null)
 {
     TypeKey   = typeKey.MustNotBeEmpty(nameof(typeKey));
     Overrides = overrides;
     HashCode  = Overrides == null ? TypeKey.HashCode : Equality.CreateHashCode(TypeKey, overrides);
 }