private Expression BuildWriterItem(IMappingAssociation association, Expression from, Expression to, ParameterExpression explicitProperties) { if ((association.Direction & MappingDirection.Write) != MappingDirection.Write) { return(null); } var converter = association as IConvertionAssociation; var component = association as IComponentAssociation; var donor = association.Target.Apply(@from); var acceptor = association.Source.Apply(to); Expression result; if (component != null) { //todo: probably should filterout expand somehow. E.g. 'foo.id' should become 'id'. Now simply not passing outer expand result = BuildWriterBody(donor, acceptor, null); if (result.NodeType == ExpressionType.Default && result.Type == typeof(void)) { return(null); } } else { PropertyInfo prop; if (!acceptor.TryGetProperty(out prop)) { throw new InvalidOperationException( string.Format("Mapping from source:{0} to target:{1} marked as writable but source is not a property access expression", association.Source.Stringify(), association.Target.Stringify()) ); } result = Expression.Assign( acceptor, converter == null ? donor : converter.TargetConverter.Expression.Apply(donor) ); } if (!(donor.Type.IsValueType || (result.NodeType == ExpressionType.Assign && ((BinaryExpression)result).Right == donor))) { result = Expression.IfThenElse( donor.CreateCheckForDefault(), Expression.Assign(acceptor, acceptor.Type.GetDefaultExpression()), result ); } if (explicitProperties != null) { result = Expression.IfThen( Expression.OrElse( explicitProperties.CreateCheckForDefault(), explicitProperties.CreateContains(Expression.Constant(association.Key, typeof(string))) ), result ); } return(result); }
private Expression BuildReaderItem(IMappingAssociation association, Expression from, ParameterExpression expands) { if ((association.Direction & MappingDirection.Read) != MappingDirection.Read) { return(null); } var converter = association as IConvertionAssociation; var collection = association as ICollectionAssociation; var component = association as IComponentAssociation; var expandable = association as IExpandableAssociation; Expression result; var donor = association.Source.Apply(from); var targetType = association.Target.ReturnType; if (collection != null) { LambdaExpression selector; //selector = new component { ... } if (component != null) { var param = Expression.Parameter(collection.SourceItemType); //todo: probably should filterout expand somehow. E.g. 'foo.id' should become 'id'. Now simply not passing outer expand var body = BuildReaderBody(param, collection.TargetItemType, null); selector = Expression.Lambda(body, param); } //selector = converter else if (converter != null) { selector = converter.TargetConverter.Expression; } else { throw new InvalidOperationException(); } // from.prop.select(selector).toarray().asenumerable() result = Expression.Convert( Expression.Call( ToArray.MakeGenericMethod(collection.TargetItemType), Expression.Call( Select.MakeGenericMethod(collection.SourceItemType, collection.TargetItemType), donor, selector ) ), targetType ); } else { // new component { .... } if (component != null) { //todo: probably should filterout expand somehow. E.g. 'foo.id' should become 'id'. Now simply not passing outer expand result = BuildReaderBody(donor, targetType, null); } //-or- converter(from.prop) else if (converter != null) { result = converter.SourceConverter.Expression.Apply(donor); } // from.prop else { result = donor; } } // expands.contains({key}) ? {exp} : null if (result != null && expands != null && expandable != null && expandable.Expand) { result = Expression.Condition( expands.CreateContains(Expression.Constant(association.Key, typeof(string))), result, targetType.GetDefaultExpression() ); } // from.prop != null ? null : {exp} if (!(donor.Type.IsValueType || result == donor)) { result = Expression.Condition( donor.CreateCheckForDefault(), targetType.GetDefaultExpression(), result ); } return(result); }