protected Expression GetMemberMappings(TypeMapping typeMapping)
        {
            var context = new ReferenceMapperContext(typeMapping.TypePair.SourceType,
                                                     typeMapping.TypePair.TargetType, typeMapping);

            //since nested selectors are supported, we sort membermappings to grant
            //that we assign outer objects first
            var memberMappings = typeMapping.MemberMappings.Values.ToList();

            if (typeMapping.IgnoreMemberMappingResolvedByConvention)
            {
                memberMappings = memberMappings.Where(mapping =>
                                                      mapping.MappingResolution != MappingResolution.RESOLVED_BY_CONVENTION).ToList();
            }

            var memberMappingExps = memberMappings
                                    .Where(mapping => !mapping.Ignore)
                                    .Where(mapping => !mapping.SourceMember.Ignore)
                                    .Where(mapping => !mapping.TargetMember.Ignore)
                                    .OrderBy(mm => mm, _memberComparer)
                                    .Select(mapping =>
            {
                if (mapping.Mapper is ReferenceMapper)
                {
                    return(GetComplexMemberExpression(mapping));
                }

                return(GetSimpleMemberExpression(mapping));
            }).ToList();

            return(!memberMappingExps.Any() ? (Expression)Expression.Empty() : Expression.Block(memberMappingExps));
        }
Example #2
0
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;
            var targetCollectionInsertionMethod = GetTargetCollectionInsertionMethod(context);

            if (context.IsSourceElementTypeBuiltIn || context.IsTargetElementTypeBuiltIn)
            {
                return(Expression.Block(SimpleCollectionLoop
                                        (
                                            context.SourceInstance, context.SourceCollectionElementType,
                                            context.TargetInstance, context.TargetCollectionElementType,
                                            targetCollectionInsertionMethod,
                                            context.SourceCollectionLoopingVar
                                        )));
            }

            return(Expression.Block(ComplexCollectionLoop
                                    (
                                        context.SourceInstance, context.SourceCollectionElementType,
                                        context.TargetInstance, context.TargetCollectionElementType,
                                        targetCollectionInsertionMethod,
                                        context.SourceCollectionLoopingVar,
                                        context.ReferenceTracker,
                                        context.Mapper
                                    )));
        }
Example #3
0
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;

            //1. Reverse the Stack by creating a new temporary Stack passing source as input
            //2. Read items from the newly created temporary stack and add items to the target

            var paramType = new Type[] { typeof(IEnumerable <>)
                                         .MakeGenericType(context.SourceCollectionElementType) };

            var tempCollectionType            = this.GetTemporaryCollectionType(context);
            var tempCollectionConstructorInfo = tempCollectionType.GetConstructor(paramType);
            var tempCollection = Expression.Parameter(tempCollectionType, "tempCollection");

            var newTempCollectionExp = Expression.New(tempCollectionConstructorInfo, context.SourceInstance);

            if (context.IsTargetElementTypeBuiltIn)
            {
                return(Expression.Block
                       (
                           new[] { tempCollection },

                           Expression.Assign(tempCollection, newTempCollectionExp),
                           SimpleCollectionLoop(context, tempCollection, context.TargetInstance)
                       ));
            }

            return(Expression.Block
                   (
                       new[] { tempCollection },

                       Expression.Assign(tempCollection, newTempCollectionExp),
                       CollectionLoopWithReferenceTracking(context, tempCollection, context.TargetInstance)
                   ));
        }
Example #4
0
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;

            /* By default I try to retrieve the item-insertion method of the collection.
             * The exact name of the method can be overridden so that, for example,
             * on Queue you search for 'Enqueue'. The default method name searched is 'Add'.
             *
             * If the item-insertion method does not exist, try to retrieve a constructor
             * which takes as its only parameter 'IEnumerable<T>'. If this constructor
             * exists a temporary List<T> is created and then passed to the constructor.
             *
             * If neither the item insertion method nor the above constructor exist
             * an exception is thrown
             */

            /* -Typically a Costructor(IEnumerable<T>) is faster than AddRange that is faster than Add.
             *  By the way Construcor( capacity ) + AddRange has roughly the same performance of Construcor( IEnumerable<T> ).
             */

            bool isUpdateCollection = /*context.Options.ReferenceBehavior == ReferenceBehaviors.USE_TARGET_INSTANCE_IF_NOT_NULL &&*/
                                      context.Options.CollectionBehavior == CollectionBehaviors.UPDATE;

            bool isMerge = /*context.Options.ReferenceBehavior == ReferenceBehaviors.USE_TARGET_INSTANCE_IF_NOT_NULL &&*/
                           context.Options.CollectionBehavior == CollectionBehaviors.MERGE;

            var targetCollectionInsertionMethod = GetTargetCollectionInsertionMethod(context);

            if (context.IsSourceElementTypeBuiltIn || context.IsTargetElementTypeBuiltIn ||
                context.IsSourceElementTypeStruct || context.IsTargetElementTypeStruct)
            {
                return(Expression.Block
                       (
                           isMerge ? Expression.Empty() : GetTargetCollectionClearExpression(context),

                           SimpleCollectionLoop(context.SourceInstance, context.SourceCollectionElementType,
                                                context.TargetInstance, context.TargetCollectionElementType,
                                                targetCollectionInsertionMethod, context.SourceCollectionLoopingVar)
                       ));
            }

            return(Expression.Block
                   (
                       GetTargetCollectionClearExpression(context),

                       isUpdateCollection ? GetUpdateCollectionExpression(context)
                    : ComplexCollectionLoop(context.SourceInstance, context.SourceCollectionElementType,
                                            context.TargetInstance, context.TargetCollectionElementType,
                                            targetCollectionInsertionMethod, context.SourceCollectionLoopingVar, context.ReferenceTracker, context.Mapper)
                   ));
        }
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;

            /* By default I try to retrieve the item-insertion method of the collection.
             * The exact name of the method can be overridden so that, for example,
             * on Queue you search for 'Enqueue'. The default method name searched is 'Add'.
             *
             * If the item-insertion method does not exist, try to retrieve a constructor
             * which takes as its only parameter 'IEnumerable<T>'. If this constructor
             * exists a temporary List<T> is created and then passed to the constructor.
             *
             * If neither the item insertion method nor the above constructor exist
             * an exception is thrown
             */

            /* -Typically a Costructor(IEnumerable<T>) is faster than AddRange that is faster than Add.
             *  By the way Construcor( capacity ) + AddRange has roughly the same performance of Construcor( IEnumerable<T> ).
             */

            var clearMethod = GetTargetCollectionClearMethod(context);

            if (clearMethod == null && context.Options.CollectionMappingStrategy == CollectionMappingStrategies.RESET)
            {
                string msg = $@"Cannot reset the collection. Type '{nameof( context.TargetInstance.Type )}' does not provide a Clear method";
                throw new Exception(msg);
            }

            if (context.IsSourceElementTypeBuiltIn || context.IsTargetElementTypeBuiltIn)
            {
                return(Expression.Block
                       (
                           context.Options.CollectionMappingStrategy == CollectionMappingStrategies.RESET ?
                           Expression.Call(context.TargetInstance, clearMethod) : (Expression)Expression.Empty(),

                           SimpleCollectionLoop(context, context.SourceInstance, context.TargetInstance)
                       ));
            }

            return(Expression.Block
                   (
                       context.Options.CollectionMappingStrategy == CollectionMappingStrategies.RESET ?
                       Expression.Call(context.TargetInstance, clearMethod) : (Expression)Expression.Empty(),

                       CollectionLoopWithReferenceTracking(context, context.SourceInstance, context.TargetInstance)
                   ));
        }
Example #6
0
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as DictionaryMapperContext;

            var addMethod = base.GetTargetCollectionInsertionMethod(context);

            var keyExpression = this.GetKeyOrValueExpression(context,
                                                             context.SourceCollectionElementKey, context.TargetCollectionElementKey);

            var valueExpression = this.GetKeyOrValueExpression(context,
                                                               context.SourceCollectionElementValue, context.TargetCollectionElementValue);

            return(Expression.Block
                   (
                       new[] { context.Mapper, context.SourceCollectionElementKey, context.SourceCollectionElementValue,
                               context.TargetCollectionElementKey, context.TargetCollectionElementValue },

                       Expression.Assign(context.Mapper, Expression.Constant(_mapper)),

                       ExpressionLoops.ForEach(context.SourceInstance,
                                               context.SourceCollectionLoopingVar, Expression.Block
                                               (
                                                   Expression.Assign(context.SourceCollectionElementKey,
                                                                     Expression.Property(context.SourceCollectionLoopingVar, nameof(DictionaryEntry.Key))),

                                                   Expression.Assign(context.SourceCollectionElementValue,
                                                                     Expression.Property(context.SourceCollectionLoopingVar, nameof(DictionaryEntry.Value))),

                                                   keyExpression,
                                                   valueExpression,

                                                   Expression.Call(context.TargetInstance, addMethod,
                                                                   context.TargetCollectionElementKey, context.TargetCollectionElementValue)
                                               ))
                   ));
        }
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;

            //1. Create a new temporary collection passing source as input
            //2. Read items from the newly created temporary collection and add items to the target

            var paramType = new Type[] { typeof(IEnumerable <>)
                                         .MakeGenericType(context.SourceCollectionElementType) };

            var tempCollectionType            = this.GetTemporaryCollectionType(context);
            var tempCollectionConstructorInfo = tempCollectionType.GetConstructor(paramType);
            var tempCollection = Expression.Parameter(tempCollectionType, "tempCollection");

            var newTempCollectionExp = Expression.New(tempCollectionConstructorInfo, context.SourceInstance);
            var temporaryCollectionInsertionMethod = this.GetTargetCollectionInsertionMethod(context);

            bool isUpdate = context.Options.CollectionBehavior == CollectionBehaviors.UPDATE;
            bool isReset  = context.Options.CollectionBehavior == CollectionBehaviors.RESET;

            if (context.IsTargetElementTypeBuiltIn)
            {
                return(Expression.Block
                       (
                           new[] { tempCollection },

                           isReset ? GetTargetCollectionClearExpression(context) : Expression.Empty(),

                           Expression.Assign(tempCollection, newTempCollectionExp),

                           SimpleCollectionLoop
                           (
                               tempCollection,
                               context.SourceCollectionElementType,
                               context.TargetInstance,
                               context.TargetCollectionElementType,
                               temporaryCollectionInsertionMethod,
                               context.SourceCollectionLoopingVar,
                               context.Mapper,
                               context.ReferenceTracker
                           )
                       ));
            }

            return(Expression.Block
                   (
                       new[] { tempCollection },

                       Expression.Assign(tempCollection, newTempCollectionExp),

                       isUpdate ? GetUpdateCollectionExpression(context) :
                       ComplexCollectionLoop
                       (
                           tempCollection,
                           context.SourceCollectionElementType,
                           context.TargetInstance,
                           context.TargetCollectionElementType,
                           temporaryCollectionInsertionMethod,
                           context.SourceCollectionLoopingVar,
                           context.ReferenceTracker,
                           context.Mapper
                       )
                   ));
        }
 protected virtual Expression GetExpressionBody(ReferenceMapperContext contextObj)
 {
     return(Expression.Empty());
 }
Example #9
0
 protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
 {
     return(Expression.Empty());
 }
Example #10
0
        protected override Expression GetExpressionBody(ReferenceMapperContext contextObj)
        {
            var context = contextObj as CollectionMapperContext;

            /* By default I try to retrieve the item-insertion method of the collection.
             * The exact name of the method can be overridden so that, for example,
             * on Queue you search for 'Enqueue'. The default method name searched is 'Add'.
             *
             * If the item-insertion method does not exist, try to retrieve a constructor
             * which takes as its only parameter 'IEnumerable<T>'. If this constructor
             * exists a temporary List<T> is created and then passed to the constructor.
             *
             * If neither the item insertion method nor the above constructor exist
             * an exception is thrown
             */

            /* -Typically a Costructor(IEnumerable<T>) is faster than AddRange that is faster than Add.
             *  By the way Construcor( capacity ) + AddRange has roughly the same performance of Construcor( IEnumerable<T> ).
             */

            //reset only if we keep using the same target instance
            bool isResetCollection = context.Options.ReferenceBehavior != ReferenceBehaviors.CREATE_NEW_INSTANCE &&
                                     context.Options.CollectionBehavior == CollectionBehaviors.RESET;

            bool isUpdateCollection = /*context.Options.ReferenceBehavior == ReferenceBehaviors.USE_TARGET_INSTANCE_IF_NOT_NULL &&*/
                                      context.Options.CollectionBehavior == CollectionBehaviors.UPDATE;

            var targetCollectionInsertionMethod = GetTargetCollectionInsertionMethod(context);

            //if( context.SourceCollectionElementType.IsInterface )
            //{
            //    throw new NotImplementedException( "collections of interface element type not fully supported yet" );
            //    //especially interface -> simple type
            //}

            if ((context.IsSourceElementTypeBuiltIn || context.IsTargetElementTypeBuiltIn ||
                 context.SourceCollectionElementType.IsValueType || context.TargetCollectionElementType.IsValueType))
            {
                return(Expression.Block
                       (
                           isResetCollection ? GetTargetCollectionClearExpression(context) : Expression.Empty(),

                           SimpleCollectionLoop(context.SourceInstance, context.SourceCollectionElementType,
                                                context.TargetInstance, context.TargetCollectionElementType,
                                                targetCollectionInsertionMethod, context.SourceCollectionLoopingVar,
                                                context.Mapper, context.ReferenceTracker)
                       ));
            }

            return(Expression.Block
                   (
                       isResetCollection ? GetTargetCollectionClearExpression(context) : Expression.Empty(),

                       isUpdateCollection ? GetUpdateCollectionExpression(context)
                    : ComplexCollectionLoop
                       (
                           context.SourceInstance,
                           context.SourceCollectionElementType,
                           context.TargetInstance,
                           context.TargetCollectionElementType,
                           targetCollectionInsertionMethod,
                           context.SourceCollectionLoopingVar,
                           context.ReferenceTracker,
                           context.Mapper,
                           context
                       )
                   ));
        }