public ConstructedValueExpression Compile(MapTypeContext context) { if (!context.TargetType.IsSupportedPrimitiveType() && context.TargetType != typeof(object)) { return(ConstructedValueExpression.Nothing); } var column = context.SingleColumn(); if (column == null) { return(ConstructedValueExpression.Nothing); } // Pull the value out of the reader into the rawVar var rawVar = context.CreateVariable(typeof(object), "raw"); var getRawStmt = Expression.Assign( rawVar, Expression.Call( context.RecordParameter, _getValueMethod, Expression.Constant(column.Index) ) ); var rawConvertExpr = MapScalar(context.TargetType, column, rawVar); column.MarkMapped(); return(new ConstructedValueExpression(new[] { getRawStmt }, rawConvertExpr, new[] { rawVar })); }
private ConstructedValueExpression CompileArrayOfScalar(MapTypeContext context, ConstructorInfo constructor, List <ColumnInfo> columns, Type elementType) { var arrayVar = context.CreateVariable(context.TargetType, "array"); var expressions = new List <Expression>(); var variables = new List <ParameterExpression>(); variables.Add(arrayVar); expressions.Add( Expression.Assign( arrayVar, Expression.New( constructor, Expression.Constant(columns.Count) ) ) ); for (int i = 0; i < columns.Count; i++) { var columnState = context.GetSubstateForColumn(columns[i], elementType, null); var getScalarExpression = _scalars.Compile(columnState); expressions.AddRange(getScalarExpression.Expressions); expressions.Add( Expression.Assign( Expression.ArrayAccess( arrayVar, Expression.Constant(i) ), getScalarExpression.FinalValue ) ); variables.AddRange(getScalarExpression.Variables); } return(new ConstructedValueExpression(expressions, arrayVar, variables)); }
public static ConstructedValueExpression GetMaybeInstantiateDictionaryExpression(MapTypeContext context, ConstructorInfo constructor) { var newInstance = context.CreateVariable(context.TargetType, "dictionary"); if (context.GetExisting == null) { // There's no way to get an existing value, so call the parameterless constructor var getNewInstanceExpr = Expression.Assign( newInstance, Expression.New(constructor) ); return(new ConstructedValueExpression(new[] { getNewInstanceExpr }, newInstance, new[] { newInstance })); } // Try to get the existing value. If we have it return it. Otherwise call the default // parameterless constructor var tryGetExistingInstanceExpr = Expression.Assign( newInstance, Expression.Condition( Expression.Equal( context.GetExisting, Expression.Constant(null) ), Expression.Convert( Expression.New(constructor), context.TargetType ), Expression.Convert(context.GetExisting, context.TargetType) ) ); return(new ConstructedValueExpression(new[] { tryGetExistingInstanceExpr }, newInstance, new[] { newInstance })); }
public static ConstructedValueExpression GetMaybeInstantiateCollectionExpression(MapTypeContext context, ConstructorInfo constructor) { var newInstance = context.CreateVariable(context.TargetType, "list"); if (context.GetExisting == null) { // if we don't have an expression to get an existing slot, just create new by // calling the default parameterless constructor on the collection type var createNewExpr = Expression.Assign( newInstance, Expression.New(constructor) ); return(new ConstructedValueExpression(new[] { createNewExpr }, newInstance, new[] { newInstance })); } // Try to get the existing value. If it's null, just create new with the default // parameterless constructor. If it's not null we can return it. var getExistingExpr = Expression.Assign( newInstance, Expression.Condition( Expression.Equal( context.GetExisting, Expression.Constant(null) ), Expression.Convert( Expression.New(constructor), context.TargetType ), Expression.Convert(context.GetExisting, context.TargetType) ) ); return(new ConstructedValueExpression(new[] { getExistingExpr }, newInstance, new[] { newInstance })); }
private ConstructedValueExpression AddInstantiationExpressionForObjectInstance(MapTypeContext context) { var instanceVar = context.CreateVariable(context.TargetType, "instance"); var typeInfo = context.Settings.GetTypeSettings(context.TargetType); var defaultSubtypeInfo = typeInfo.GetDefault(); var defaultInstantiationExpression = AddInstantiationExpressionForSpecificType(context, defaultSubtypeInfo, instanceVar); var subclasses = typeInfo.GetSpecificTypes().ToList(); // If we have no configured subclass predicates, instantiate the target type directly if (subclasses.Count == 0) { return(new ConstructedValueExpression(defaultInstantiationExpression.Expressions, instanceVar, defaultInstantiationExpression.Variables.Concat(new[] { instanceVar }))); } // If we have configured subclass predicates, unroll the loop and write expressions for // all cases. The default case will be executed if no subclass predicates match. var endLabel = context.CreateLabel("haveinstance"); var expressions = new List <Expression>(); foreach (var subclass in subclasses.Where(s => s.Predicate != null)) { var instantiateExpressions = AddInstantiationExpressionForSpecificType(context, subclass, instanceVar); // Check the subclass predicate. If it matches, we enter into a block where we // create the subclass instance and then jump to the end label. Otherwise we // fall through to the next subclass. expressions.Add( Expression.IfThen( Expression.Call( Expression.Constant(subclass.Predicate.Target), subclass.Predicate.Method, context.RecordParameter ), Expression.Block( instantiateExpressions.Variables, instantiateExpressions.Expressions.Concat(new[] { Expression.Goto(endLabel.Target) }) ) ) ); } // A block where we fall back to the default instantiation rules for the type, and then // fall through to the endLabel. The block here allows us to scope variables a little // more tightly expressions.Add( Expression.Block( defaultInstantiationExpression.Variables, defaultInstantiationExpression.Expressions ) ); expressions.Add(endLabel); return(new ConstructedValueExpression(expressions, instanceVar, new[] { instanceVar })); }
private ConstructedValueExpression CompileArrayOfCustomObject(MapTypeContext context, Type elementType, ConstructorInfo constructor) { var expressions = new List <Expression>(); var variables = new List <ParameterExpression>(); // We don't loop here because we need to know how many items we have in the array and we // can't calculate that because the custom object might consume any number of columns. We don't // know until after each iteration has returned how many columns are left. We could map to // a List and then .ToArray() to get the array, but that seems wasteful. var arrayVar = context.CreateVariable(context.TargetType, "array"); variables.Add(arrayVar); var elementState = context.ChangeTargetType(elementType); var result = _customObjects.Compile(elementState); expressions.AddRange(result.Expressions); // Create a new array with a length of 1 expressions.Add( Expression.Assign( arrayVar, Expression.New( constructor, Expression.Constant(1) ) ) ); // Set the value to the first slot in the array expressions.Add( Expression.Assign( Expression.ArrayAccess( arrayVar, Expression.Constant(0) ), result.FinalValue ) ); variables.AddRange(result.Variables); return(new ConstructedValueExpression(expressions, arrayVar, variables)); }