コード例 #1
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));
        }
        private static ConstructorInfo FindConstructorOfClosedConstructedGenericType(ResolveExpressionContext context, ConstructorInstantiationInfo instantiationInfo)
        {
            var constructors      = context.ResolvedGenericRegistrationTypeInfo.DeclaredConstructors.AsReadOnlyList();
            var targetConstructor = context.FindResolvedGenericMethod(instantiationInfo.ConstructorInfo, constructors);

            if (targetConstructor != null)
            {
                return(targetConstructor);
            }

            throw new ResolveException($"The constructor for the closed constructed generic type \"{context.RequestedType}\" that matches the generic type definition's constructor \"{instantiationInfo.ConstructorInfo}\" could not be found. This exception should actually never happen, unless there is a bug in class \"{nameof(ConstructorInstantiationInfoFactory)}\" or you messed with the .NET type system badly.");
        }
        protected override Expression Create(ConstructorInstantiationInfo instantiationInfo,
                                             ResolveExpressionContext context,
                                             Expression[] parameterExpressions)
        {
            if (context.IsResolvingGenericTypeDefinition == false)
            {
                return(Expression.New(instantiationInfo.ConstructorInfo, parameterExpressions));
            }

            var targetConstructor = FindConstructorOfClosedConstructedGenericType(context, instantiationInfo);

            return(Expression.New(targetConstructor, parameterExpressions));
        }
コード例 #4
0
        private Expression CreateConstructionExpression(ResolveExpressionContext context)
        {
            // Create the expression that instantiates the target object
            var instantiationInfo    = context.Registration.TypeConstructionInfo.InstantiationInfo;
            var parameterExpressions = ResolveDependenciesRecursivelyIfNecessary(instantiationInfo.InstantiationDependencies, context);

            // Use the correct factory to create the expression that instantiates the target type
            if (_instantiationExpressionFactories.TryGetValue(instantiationInfo.GetType(), out var instantiationExpressionFactory) == false)
            {
                throw new InvalidOperationException($"There is no instantiationExpressionFactory present for \"{instantiationInfo.GetType()}\". Please check that \"{nameof(CompiledLinqExpressionFactory)}\" is created with all necessary dependencies in \"{nameof(ContainerServices)}\".");
            }
            var instantiationExpression = instantiationExpressionFactory.Create(instantiationInfo, context, parameterExpressions);

            // If there are no instance manipulations, then simply return the instantiation expression
            var instanceManipulations = context.Registration.TypeConstructionInfo.InstanceManipulations;

            if (instanceManipulations.IsNullOrEmpty())
            {
                return(instantiationExpression);
            }

            // Else we need a block that holds the target object in a variable and performs each instance manipulation in one statement
            // The first statement is always the assignment of the instantiationExpression to a variable that holds the instance
            var instanceVariableExpression = Expression.Variable(context.InstanceType);
            var assignVariableExpression   = Expression.Assign(instanceVariableExpression, instantiationExpression);
            var blockExpressions           = new Expression[instanceManipulations.Count + 2]; // +2 for assignment and return statements

            blockExpressions[0] = assignVariableExpression;                                   // variable assign statement

            // The subsequent statements hold the instance manipulations (e.g. property injection, field injection, calling methods, etc.)
            for (var i = 0; i < instanceManipulations.Count; i++)
            {
                var instanceManipulation = instanceManipulations[i];
                parameterExpressions = ResolveDependenciesRecursivelyIfNecessary(instanceManipulation.Dependencies, context);

                if (_instanceManipulationExpressionFactories.TryGetValue(instanceManipulation.GetType(), out var instanceManipulationExpressionFactory) == false)
                {
                    throw new InvalidOperationException($"There is no instanceManipulationExpressionFactory present for \"{instanceManipulation.GetType()}\". Please check that \"{nameof(CompiledLinqExpressionFactory)}\" is created with all necessary dependencies in \"{nameof(ContainerServices)}\".");
                }
                blockExpressions[i + 1] = instanceManipulationExpressionFactory.Create(instanceManipulation, instanceVariableExpression, context, parameterExpressions);
            }

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

            return(Expression.Block(context.InstanceType, new[] { instanceVariableExpression }, blockExpressions));
        }
 protected abstract Expression Create(T instanceManipulation, ParameterExpression instanceVariableExpression, ResolveExpressionContext context, Expression[] parameterExpressions);
 public Expression Create(InstanceManipulation instanceManipulation, ParameterExpression instanceVariableExpression, ResolveExpressionContext context, Expression[] parameterExpressions)
 {
     return(Create(instanceManipulation.MustBeOfType <T>(nameof(instanceManipulation)), instanceVariableExpression.MustNotBeNull(nameof(instanceVariableExpression)), context, parameterExpressions));
 }
        protected override Expression Create(FieldInjection fieldInjection, ParameterExpression instanceVariableExpression, ResolveExpressionContext context, Expression[] parameterExpressions)
        {
            parameterExpressions.MustHaveCount(1, nameof(parameterExpressions));

            var targetField = fieldInjection.TargetField;

            if (context.IsResolvingGenericTypeDefinition)
            {
                targetField = context.ResolvedGenericRegistrationType.GetRuntimeField(targetField.Name);
            }

            return(Expression.Assign(Expression.Field(instanceVariableExpression, targetField), parameterExpressions[0]));
        }
 protected abstract Expression Create(T instantiationInfo, ResolveExpressionContext context, Expression[] parameterExpressions);
 public Expression Create(InstantiationInfo instantiationInfo, ResolveExpressionContext context, Expression[] parameterExpressions)
 {
     return(Create(instantiationInfo.MustBeOfType <T>(nameof(instantiationInfo)), context, parameterExpressions));
 }
        protected override Expression Create(StaticMethodInstantiationInfo instantiationInfo, ResolveExpressionContext context, Expression[] parameterExpressions)
        {
            if (instantiationInfo.TypeKey.Type.IsGenericTypeDefinition() == false)
            {
                return(Expression.Call(instantiationInfo.StaticMethod, parameterExpressions));
            }

            if (instantiationInfo.StaticMethod.DeclaringType.IsGenericTypeDefinition())
            {
                var closedConstructedStaticType = instantiationInfo.StaticMethod.DeclaringType.MakeGenericType(context.ResolvedGenericRegistrationTypeInfo.GenericTypeArguments);
                var closedConstructedMethods    = closedConstructedStaticType.GetTypeInfo().GetDeclaredMethods(instantiationInfo.StaticMethod.Name).AsReadOnlyList();
                var staticMethodOfClosedConstructedStaticType = context.FindResolvedGenericMethod(instantiationInfo.StaticMethod, closedConstructedMethods);
                if (staticMethodOfClosedConstructedStaticType != null)
                {
                    return(Expression.Call(staticMethodOfClosedConstructedStaticType, parameterExpressions));
                }
                throw new ResolveException($"The static method \"{instantiationInfo.StaticMethod}\" could not be found for the closed constructed type \"{closedConstructedStaticType}\". This exception should actually never happen, unless there is a bug in class \"{nameof(StaticMethodInstantiationInfoFactory)}\" or you messed with the .NET type system badly.");
            }

            var closedConstructedGenericMethod = instantiationInfo.StaticMethod.MakeGenericMethod(context.ResolvedGenericRegistrationTypeInfo.GenericTypeArguments);

            return(Expression.Call(closedConstructedGenericMethod, parameterExpressions));
        }
コード例 #11
0
        private Expression[] ResolveDependenciesRecursivelyIfNecessary(IReadOnlyList <Dependency> dependencies, ResolveExpressionContext context)
        {
            if (dependencies.IsNullOrEmpty())
            {
                return(null);
            }

            var resolvedDependencyExpressions = new Expression[dependencies.Count];

            for (var i = 0; i < resolvedDependencyExpressions.Length; i++)
            {
                var dependency     = dependencies[i];
                var dependencyType = dependency.TargetType;
                dependencyType = context.ResolveGenericTypeParameterIfNecessary(dependencyType);
                dependencyType = context.ResolveOpenConstructedGenericTypeIfNecessary(dependencyType);

                // Check if the dependency is overridden - if yes, then resolve it via the ResolveContext parameter
                if (context.DependencyOverrides?.HasDependency(dependency) == true)
                {
                    resolvedDependencyExpressions[i] = Expression.Convert(Expression.Call(Expression.Call(Constants.ResolveContextParameterExpression,
                                                                                                          Constants.GetDependencyOverridesProperty),
                                                                                          Constants.GetDependencyInstanceMethod,
                                                                                          Expression.Constant(dependency)),
                                                                          dependency.TargetType);
                    continue;
                }

                resolvedDependencyExpressions[i] = CreateResolveExpressionRecursively(new TypeKey(dependencyType, dependency.TargetRegistrationName),
                                                                                      context.Container,
                                                                                      context.DependencyOverrides,
                                                                                      dependency.ResolveAll);
            }

            return(resolvedDependencyExpressions);
        }
コード例 #12
0
        protected override Expression Create(DelegateInstantiationInfo instantiationInfo, ResolveExpressionContext context, Expression[] parameterExpressions)
        {
            var methodInfo = instantiationInfo.Delegate.GetMethodInfo();

            return(Expression.Call(methodInfo, parameterExpressions));
        }
        protected override Expression Create(PropertyInjection propertyInjection, ParameterExpression instanceVariableExpression, ResolveExpressionContext context, Expression[] parameterExpressions)
        {
            var targetProperty = propertyInjection.TargetProperty;

            if (context.IsResolvingGenericTypeDefinition)
            {
                targetProperty = context.ResolvedGenericRegistrationType.GetRuntimeProperty(targetProperty.Name);
            }
            return(Expression.Call(instanceVariableExpression, targetProperty.SetMethod, parameterExpressions));
        }