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); // Resolve parameters ParameterInfo[] parameters = selectedCtor.Constructor.GetParameters(); 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(); } 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); }
private IEnumerable <Expression> CreateNewBuildupSequence(DynamicBuildPlanGenerationContext buildContext, SelectedConstructor selectedConstructor, string signature) { var parameterExpressions = this.BuildConstructionParameterExpressions(buildContext, selectedConstructor, signature); var newItemExpression = Expression.Variable(selectedConstructor.Constructor.DeclaringType, "newItem"); yield return(Expression.Call(null, SetCurrentOperationToInvokingConstructorMethod, Expression.Constant(signature), buildContext.ContextParameter)); yield return(Expression.Assign( buildContext.GetExistingObjectExpression(), Expression.Convert( Expression.New(selectedConstructor.Constructor, parameterExpressions), typeof(object)))); yield return(buildContext.GetClearCurrentOperationExpression()); }
private IEnumerable <Expression> BuildConstructionParameterExpressions(DynamicBuildPlanGenerationContext buildContext, SelectedConstructor selectedConstructor, string constructorSignature) { int i = 0; var constructionParameters = selectedConstructor.Constructor.GetParameters(); foreach (IDependencyResolverPolicy parameterResolver in selectedConstructor.GetParameterResolvers()) { yield return(buildContext.CreateParameterExpression( parameterResolver, constructionParameters[i].ParameterType, Expression.Call(null, SetCurrentOperationToResolvingParameterMethod, Expression.Constant(constructionParameters[i].Name, typeof(string)), Expression.Constant(constructorSignature), buildContext.ContextParameter))); i++; } }
private static bool IsInvalidConstructor(SelectedConstructor selectedConstructor) { return(selectedConstructor.Constructor.GetParameters().Any(pi => pi.ParameterType.IsByRef)); }