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 })); }