public override void PreBuildUp(IBuilderContext context)
        {
            Guard.ArgumentNotNull(context, "context");

            DynamicBuildPlanGenerationContext buildContext =
                (DynamicBuildPlanGenerationContext)context.Existing;

            IConstructorSelectorPolicy selector =
                context.Policies.Get <IConstructorSelectorPolicy>(context.BuildKey);

            SelectedConstructor selectedCtor = selector.SelectConstructor(context);
            // Method preamble - test if we have an existing object
            // First off, set up jump - if there's an existing object, skip us entirely
            Label existingObjectNotNull = buildContext.IL.DefineLabel();

            buildContext.EmitLoadExisting();
            buildContext.IL.Emit(OpCodes.Ldnull);
            buildContext.IL.Emit(OpCodes.Ceq);
            buildContext.IL.Emit(OpCodes.Brfalse, existingObjectNotNull);

            if (selectedCtor != null)
            {
                // Resolve parameters
                ParameterInfo[] parameters = selectedCtor.Constructor.GetParameters();

                int i = 0;
                foreach (string parameterKey in selectedCtor.GetParameterKeys())
                {
                    buildContext.EmitResolveDependency(parameters[i].ParameterType, parameterKey);
                    ++i;
                }

                // Call the constructor

                buildContext.IL.Emit(OpCodes.Newobj, selectedCtor.Constructor);
                buildContext.EmitStoreExisting();
            }
            else
            {
                // If we get here, object has no constructors. It's either
                // an interface or a primitive (like int). In this case,
                // verify that we have an Existing object, and if not,
                // throw (via helper function).
                buildContext.EmitLoadContext();
                buildContext.IL.EmitCall(OpCodes.Call, throwForNullExistingObject, null);
            }

            buildContext.IL.MarkLabel(existingObjectNotNull);
        }
Exemple #2
0
        public override void PreBuildUp(IBuilderContext context)
        {
            Guard.ArgumentNotNull(context, "context");

            DynamicBuildPlanGenerationContext buildContext =
                (DynamicBuildPlanGenerationContext)context.Existing;

            IConstructorSelectorPolicy selector =
                context.Policies.Get <IConstructorSelectorPolicy>(context.BuildKey);

            SelectedConstructor selectedCtor = selector.SelectConstructor(context);
            // Method preamble - test if we have an existing object
            // First off, set up jump - if there's an existing object, skip us entirely
            Label existingObjectNotNull = buildContext.IL.DefineLabel();

            buildContext.EmitLoadExisting();
            buildContext.IL.Emit(OpCodes.Ldnull);
            buildContext.IL.Emit(OpCodes.Ceq);
            buildContext.IL.Emit(OpCodes.Brfalse, existingObjectNotNull);

            // Verify we're not attempting to create an instance of an interface
            buildContext.EmitLoadContext();
            buildContext.IL.EmitCall(OpCodes.Call, throwForAttemptingToConstructInterface, null);

            if (selectedCtor != null)
            {
                string       signatureString      = CreateSignatureString(selectedCtor.Constructor);
                LocalBuilder currentParameterName = buildContext.IL.DeclareLocal(typeof(string));

                // Resolve parameters
                ParameterInfo[] parameters = selectedCtor.Constructor.GetParameters();

                buildContext.IL.BeginExceptionBlock();

                int i = 0;
                foreach (string parameterKey in selectedCtor.GetParameterKeys())
                {
                    buildContext.IL.Emit(OpCodes.Ldstr, parameters[i].Name);
                    buildContext.IL.Emit(OpCodes.Stloc, currentParameterName);
                    buildContext.EmitResolveDependency(parameters[i].ParameterType, parameterKey);
                    ++i;
                }

                // Call the constructor

                buildContext.IL.Emit(OpCodes.Ldnull);
                buildContext.IL.Emit(OpCodes.Stloc, currentParameterName);

                buildContext.IL.Emit(OpCodes.Newobj, selectedCtor.Constructor);
                buildContext.EmitStoreExisting();

                buildContext.IL.BeginCatchBlock(typeof(Exception));
                Label exceptionOccuredInResolution = buildContext.IL.DefineLabel();

                buildContext.IL.Emit(OpCodes.Ldloc, currentParameterName);
                buildContext.IL.Emit(OpCodes.Ldnull);
                buildContext.IL.Emit(OpCodes.Ceq);
                buildContext.IL.Emit(OpCodes.Brfalse, exceptionOccuredInResolution);
                buildContext.IL.Emit(OpCodes.Rethrow);

                buildContext.IL.MarkLabel(exceptionOccuredInResolution);
                buildContext.IL.Emit(OpCodes.Ldloc, currentParameterName);
                buildContext.IL.Emit(OpCodes.Ldstr, signatureString);
                buildContext.EmitLoadContext();
                buildContext.IL.EmitCall(OpCodes.Call, throwForResolutionFailed, null);

                buildContext.IL.EndExceptionBlock();
            }
            else
            {
                // If we get here, object has no constructors. It's either
                // an interface or a primitive (like int). In this case,
                // verify that we have an Existing object, and if not,
                // throw (via helper function).
                buildContext.EmitLoadContext();
                buildContext.IL.EmitCall(OpCodes.Call, throwForNullExistingObject, null);
            }

            buildContext.IL.MarkLabel(existingObjectNotNull);
        }
        public override void PreBuildUp(IBuilderContext context)
        {
            Guard.ArgumentNotNull(context, "context");

            DynamicBuildPlanGenerationContext buildContext =
                (DynamicBuildPlanGenerationContext)context.Existing;

            IPolicyList resolverPolicyDestination;
            IConstructorSelectorPolicy selector =
                context.Policies.Get <IConstructorSelectorPolicy>(context.BuildKey, out resolverPolicyDestination);

            SelectedConstructor selectedCtor = selector.SelectConstructor(context, resolverPolicyDestination);

            GuardTypeIsNonPrimitive(context, selectedCtor);

            // Method preamble - test if we have an existing object
            // First off, set up jump - if there's an existing object, skip us entirely
            Label existingObjectNotNull = buildContext.IL.DefineLabel();

            if (!buildContext.TypeToBuild.IsValueType)
            {
                buildContext.EmitLoadExisting();
                buildContext.IL.Emit(OpCodes.Brtrue, existingObjectNotNull);
            }

            // Verify we're not attempting to create an instance of an interface
            buildContext.EmitLoadContext();
            buildContext.IL.EmitCall(OpCodes.Call, throwForAttemptingToConstructInterface, null);

            if (selectedCtor != null)
            {
                string signatureString = CreateSignatureString(selectedCtor.Constructor);

                // Resolve parameters
                ParameterInfo[] parameters = selectedCtor.Constructor.GetParameters();

                if (!parameters.Any(pi => pi.ParameterType.IsByRef))
                {
                    int i = 0;
                    foreach (string parameterKey in selectedCtor.GetParameterKeys())
                    {
                        // Set the current operation
                        buildContext.IL.Emit(OpCodes.Ldstr, parameters[i].Name);
                        buildContext.IL.Emit(OpCodes.Ldstr, signatureString);
                        buildContext.EmitLoadContext();
                        buildContext.IL.EmitCall(OpCodes.Call, setCurrentOperationToResolvingParameter, null);

                        // Resolve the parameter
                        buildContext.EmitResolveDependency(parameters[i].ParameterType, parameterKey);
                        ++i;
                    }

                    // Set the current operation
                    buildContext.IL.Emit(OpCodes.Ldstr, signatureString);
                    buildContext.EmitLoadContext();
                    buildContext.IL.EmitCall(OpCodes.Call, setCurrentOperationToInvokingConstructor, null);

                    // Call the constructor
                    buildContext.IL.Emit(OpCodes.Newobj, selectedCtor.Constructor);

                    // Store the existing object
                    buildContext.EmitStoreExisting();

                    // Clear the current operation
                    buildContext.EmitClearCurrentOperation();

                    // Store existing object back into context - makes it available for future resolvers
                    buildContext.EmitLoadContext();
                    buildContext.EmitLoadExisting();
                    if (buildContext.TypeToBuild.IsValueType)
                    {
                        buildContext.IL.Emit(OpCodes.Box, buildContext.TypeToBuild);
                    }
                    buildContext.IL.EmitCall(OpCodes.Callvirt, setExistingInContext, null);

                    // Is this object a per-build singleton? If so, then emit code to stuff in
                    // the appropriate lifetime manager.
                    buildContext.EmitLoadContext();
                    buildContext.IL.EmitCall(OpCodes.Call, setPerBuildSingleton, null);
                }
                else
                {
                    // if we get here the selected constructor has ref or out parameters.
                    buildContext.EmitLoadContext();
                    buildContext.IL.Emit(OpCodes.Ldstr, signatureString);
                    buildContext.IL.EmitCall(OpCodes.Call, throwForNullExistingObjectWithInvalidConstructor, null);
                }
            }
            else
            {
                // If we get here, object has no constructors. It's either
                // an interface or a primitive (like int). In this case,
                // verify that we have an Existing object, and if not,
                // throw (via helper function).
                buildContext.EmitLoadContext();
                buildContext.IL.EmitCall(OpCodes.Call, throwForNullExistingObject, null);
            }

            buildContext.IL.MarkLabel(existingObjectNotNull);
        }