public Expression CollectionLoopWithReferenceTracking(CollectionMapperContext context,
                                                              ParameterExpression sourceCollection, ParameterExpression targetCollection)
        {
            var targetCollectionInsertionMethod = GetTargetCollectionInsertionMethod(context);

            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{nameof( context.TargetInstance.Type )}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            var itemMapping = MapperConfiguration[context.SourceCollectionLoopingVar.Type,
                                                  context.TargetCollectionElementType].MappingExpression;

            var newElement = Expression.Variable(context.TargetCollectionElementType, "newElement");

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

                       ExpressionLoops.ForEach(sourceCollection, context.SourceCollectionLoopingVar, Expression.Block
                                               (
                                                   LookUpBlock(context, context.SourceCollectionLoopingVar, newElement),
                                                   Expression.Call(targetCollection, targetCollectionInsertionMethod, newElement)
                                               )
                                               )));
        }
Exemple #2
0
        protected virtual Expression SimpleCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                          ParameterExpression targetCollection, Type targetCollectionElementType,
                                                          MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar)
        {
            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{targetCollection.Type}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            var itemMapping = MapperConfiguration[sourceCollectionElementType,
                                                  targetCollectionElementType].MappingExpression;

            Expression loopBody = Expression.Call
                                  (
                targetCollection, targetCollectionInsertionMethod,

                itemMapping.Body.ReplaceParameter(sourceCollectionLoopingVar,
                                                  itemMapping.Parameters[0].Name)
                                  );

            return(ExpressionLoops.ForEach(sourceCollection,
                                           sourceCollectionLoopingVar, loopBody));
        }
        protected Expression SimpleCollectionLoop(CollectionMapperContext context,
                                                  ParameterExpression sourceCollection, ParameterExpression targetCollection)
        {
            var targetCollectionInsertionMethod = GetTargetCollectionInsertionMethod(context);

            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{nameof( context.TargetInstance.Type )}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            var itemMapping = MapperConfiguration[context.SourceCollectionElementType,
                                                  context.TargetCollectionElementType].MappingExpression;

            Expression loopBody = Expression.Call
                                  (
                targetCollection, targetCollectionInsertionMethod,
                itemMapping.Body.ReplaceParameter(
                    context.SourceCollectionLoopingVar, itemMapping.Parameters[0].Name)
                                  );

            return(ExpressionLoops.ForEach(sourceCollection,
                                           context.SourceCollectionLoopingVar, loopBody));
        }
Exemple #4
0
        public override LambdaExpression GetMappingExpression(Type source, Type target, IMappingOptions options)
        {
            //IGNORING FIELDS ON PURPOSE SINCE SUPPORTING FIELDS WILL FORCE
            //THE USER TO ALWAYS SET OPTIONATTRIBUTE.ORDER IN ORDER TO MAP BY INDEX RELIABLY
            //(REFLECTION DO NOT GUARANTEE PROPERTIES AND FIELDS TO BE RETURNED IN DECLARED ORDER
            //IN PARTICULAR IF FIELDS AND PROPERTIES DECLARATION ORDER IS MIXED
            //(eg: property, field, property, field...)

            //if( target.IsValueType && !target.IsNullable() )
            //    throw new ArgumentException( $"Value types are not supported. {target.GetPrettifiedName()} is a value type." );

            var context       = this.GetMapperContext(source, target, options);
            var targetMembers = this.SelectTargetMembers(target);

            var subParam        = Expression.Parameter(typeof(IParsedParam), "paramLoopVar");
            var subParamsAccess = Expression.Property(context.SourceInstance, nameof(ComplexParam.SubParams));

            var paramNameLowerCase = Expression.Parameter(typeof(string), "paramName");
            var paramNameExp       = Expression.Property(subParam, nameof(IParsedParam.Name));
            var paramNameToLower   = Expression.Call(paramNameExp, nameof(String.ToLower), null, null);

            var propertiesAssigns = new ComplexParamMemberExpressionBuilder(_mapper.Config)
            {
                CanMapByIndex = CanMapByIndex
            }
            .GetMemberAssignments(context, targetMembers, subParam, MapperConfiguration, paramNameLowerCase).ToArray();

            Expression paramNameDispatch = null;

            if (this.CanMapByIndex)
            {
                var paramNameIfElseChain = GetIfElseChain(propertiesAssigns);
                paramNameDispatch = paramNameIfElseChain;
            }
            else
            {
                var paramNameSwitch = GetSwitch(propertiesAssigns, paramNameLowerCase);
                paramNameDispatch = paramNameSwitch;
            }

            var expression = !propertiesAssigns.Any() ? (Expression)Expression.Empty() : Expression.Block
                             (
                new[] { subParam, paramNameLowerCase },

                ExpressionLoops.ForEach(subParamsAccess, subParam, Expression.Block
                                        (
                                            Expression.Assign(paramNameLowerCase, paramNameToLower),
                                            paramNameDispatch
                                        ))
                             );

            var delegateType = typeof(Action <, ,>).MakeGenericType(
                context.ReferenceTracker.Type, context.SourceInstance.Type,
                context.TargetInstance.Type);

            return(Expression.Lambda(delegateType, expression,
                                     context.ReferenceTracker, context.SourceInstance, context.TargetInstance));
        }
Exemple #5
0
        protected override Expression SimpleCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                           ParameterExpression targetCollection, Type targetCollectionElementType,
                                                           MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar, ParameterExpression mapper, ParameterExpression referenceTracker)
        {
            if (sourceCollectionElementType.IsInterface)
            {
                Expression <Func <object, Type, object> > getRuntimeMapping =
                    (loopingvar, targetType) => RuntimeMappingInterfaceToPrimitiveType(loopingvar, targetType);

                var itemIndex  = Expression.Parameter(typeof(int), "itemIndex");
                var newElement = Expression.Variable(targetCollectionElementType, "newElement");

                Expression loopBody = Expression.Block
                                      (
                    new[] { newElement, itemIndex },
                    Expression.Assign(itemIndex, Expression.Constant(0)),

                    ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                            (
                                                Expression.Assign(newElement, Expression.Convert(
                                                                      Expression.Invoke(getRuntimeMapping, sourceCollectionLoopingVar,
                                                                                        Expression.Constant(targetCollectionElementType)), targetCollectionElementType)),

                                                Expression.Assign(Expression.ArrayAccess(targetCollection, itemIndex), newElement),
                                                Expression.AddAssign(itemIndex, Expression.Constant(1))
                                            ))
                                      );

                return(ExpressionLoops.ForEach(sourceCollection,
                                               sourceCollectionLoopingVar, loopBody));
            }
            else
            {
                var itemMapping = MapperConfiguration[sourceCollectionElementType,
                                                      targetCollectionElementType].MappingExpression;

                var itemIndex = Expression.Parameter(typeof(int), "itemIndex");

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

                           Expression.Assign(itemIndex, Expression.Constant(0)),

                           ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                                   (
                                                       Expression.Assign(Expression.ArrayAccess(targetCollection, itemIndex),
                                                                         itemMapping.Body.ReplaceParameter(sourceCollectionLoopingVar, "sourceInstance")),

                                                       Expression.AddAssign(itemIndex, Expression.Constant(1))
                                                   ))
                       ));
            }
        }
Exemple #6
0
        protected virtual Expression ComplexCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                           ParameterExpression targetCollection, Type targetCollectionElementType,
                                                           MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar,
                                                           ParameterExpression referenceTracker, ParameterExpression mapper, CollectionMapperContext context = null)
        {
            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{targetCollection.Type}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            var newElement = Expression.Variable(targetCollectionElementType, "newElement");

            var mapping = ((Mapping)context.Options).GlobalConfig[sourceCollectionElementType, targetCollectionElementType];

            if (mapping.Source.EntryType != mapping.Source.ReturnType)
            {
                mapping = ((Mapping)context.Options).GlobalConfig[mapping.Source.ReturnType, targetCollectionElementType];
            }

            var valueGetter = mapping.Source.ValueGetter;

            /*member extraction support*/
            Expression valueExtraction = Expression.Invoke(valueGetter, sourceCollectionLoopingVar);

            if (((Mapping)context.Options).Source.MemberAccessPath.Count <= 1)
            {
                valueExtraction = sourceCollectionLoopingVar;
            }

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

                       ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                               (
                                                   Expression.IfThenElse
                                                   (
                                                       Expression.Equal(valueExtraction, Expression.Constant(null, sourceCollectionElementType)),

                                                       Expression.Call(targetCollection, targetCollectionInsertionMethod, Expression.Default(targetCollectionElementType)),

                                                       Expression.Block
                                                       (
                                                           LookUpBlock(sourceCollectionLoopingVar, newElement, referenceTracker, mapper),
                                                           Expression.Call(targetCollection, targetCollectionInsertionMethod, newElement)
                                                       )
                                                   )
                                               )
                                               )));
        }
        protected virtual Expression SimpleCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                          ParameterExpression targetCollection, Type targetCollectionElementType,
                                                          MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar,
                                                          ParameterExpression mapper, ParameterExpression referenceTracker)
        {
            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{targetCollection.Type}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            if (sourceCollectionElementType.IsInterface)
            {
                Expression <Func <object, Type, object> > getRuntimeMapping =
                    (loopingvar, targetType) => this.MapperConfiguration[loopingvar.GetType(), targetType].MappingFuncPrimitives(null, loopingvar);

                var newElement = Expression.Variable(targetCollectionElementType, "newElement");

                Expression loopBody = Expression.Block
                                      (
                    new[] { newElement },

                    Expression.Assign(newElement, Expression.Convert(
                                          Expression.Invoke(getRuntimeMapping, sourceCollectionLoopingVar,
                                                            Expression.Constant(targetCollectionElementType)), targetCollectionElementType)),

                    Expression.Call(targetCollection, targetCollectionInsertionMethod, newElement)
                                      );

                return(ExpressionLoops.ForEach(sourceCollection,
                                               sourceCollectionLoopingVar, loopBody));
            }
            else
            {
                var itemMapping = MapperConfiguration[sourceCollectionElementType,
                                                      targetCollectionElementType].MappingExpression;

                Expression loopBody = Expression.Call
                                      (
                    targetCollection, targetCollectionInsertionMethod,
                    itemMapping.Body.ReplaceParameter(sourceCollectionLoopingVar, "sourceInstance")
                                      );

                return(ExpressionLoops.ForEach(sourceCollection,
                                               sourceCollectionLoopingVar, loopBody));
            }
        }
Exemple #8
0
        public override LambdaExpression GetMappingExpression(Type source, Type target, IMappingOptions options)
        {
            var context           = (CollectionMapperContext)this.GetMapperContext(source, target, options);
            var mappingExpression = MapperConfiguration[typeof(ParsedCommand), target].MappingExpression;

            var body = ExpressionLoops.ForEach(context.SourceInstance, context.SourceCollectionLoopingVar,
                                               Expression.Invoke(mappingExpression, context.ReferenceTracker,
                                                                 context.SourceCollectionLoopingVar, context.TargetInstance));

            var delegateType = typeof(Action <, ,>).MakeGenericType(
                context.ReferenceTracker.Type, context.SourceInstance.Type,
                context.TargetInstance.Type);

            return(Expression.Lambda(delegateType, body,
                                     context.ReferenceTracker, context.SourceInstance, context.TargetInstance));
        }
Exemple #9
0
        protected override Expression ComplexCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                            ParameterExpression targetCollection, Type targetCollectionElementType,
                                                            MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar,
                                                            ParameterExpression referenceTracker, ParameterExpression mapper, CollectionMapperContext context = null)
        {
            var newElement = Expression.Variable(targetCollectionElementType, "newElement");
            var itemIndex  = Expression.Parameter(typeof(int), "itemIndex");

            return(Expression.Block
                   (
                       new[] { newElement, itemIndex },

                       ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                               (
                                                   LookUpBlock(sourceCollectionLoopingVar, newElement, referenceTracker, mapper),
                                                   Expression.Assign(Expression.ArrayAccess(targetCollection, itemIndex), newElement),

                                                   Expression.AddAssign(itemIndex, Expression.Constant(1))
                                               )
                                               )));
        }
Exemple #10
0
        protected override Expression SimpleCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                           ParameterExpression targetCollection, Type targetCollectionElementType,
                                                           MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar)
        {
            var itemMapping = MapperConfiguration[sourceCollectionElementType,
                                                  targetCollectionElementType].MappingExpression;

            var itemIndex = Expression.Parameter(typeof(int), "itemIndex");

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

                       ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                               (
                                                   Expression.Assign(Expression.ArrayAccess(targetCollection, itemIndex),
                                                                     itemMapping.Body.ReplaceParameter(sourceCollectionLoopingVar, itemMapping.Parameters[0].Name)),

                                                   Expression.AddAssign(itemIndex, Expression.Constant(1))
                                               ))
                   ));
        }
Exemple #11
0
        protected virtual Expression ComplexCollectionLoop(ParameterExpression sourceCollection, Type sourceCollectionElementType,
                                                           ParameterExpression targetCollection, Type targetCollectionElementType,
                                                           MethodInfo targetCollectionInsertionMethod, ParameterExpression sourceCollectionLoopingVar,
                                                           ParameterExpression referenceTracker, ParameterExpression mapper)
        {
            if (targetCollectionInsertionMethod == null)
            {
                string msg = $@"'{targetCollection.Type}' does not provide an insertion method. " +
                             $"Please override '{nameof( GetTargetCollectionInsertionMethod )}' to provide the item insertion method.";

                throw new Exception(msg);
            }

            var itemMapping = MapperConfiguration[sourceCollectionLoopingVar.Type,
                                                  targetCollectionElementType].MappingExpression;

            var newElement = Expression.Variable(targetCollectionElementType, "newElement");

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

                       ExpressionLoops.ForEach(sourceCollection, sourceCollectionLoopingVar, Expression.Block
                                               (
                                                   Expression.IfThenElse
                                                   (
                                                       Expression.Equal(sourceCollectionLoopingVar, Expression.Constant(null, sourceCollectionElementType)),

                                                       Expression.Call(targetCollection, targetCollectionInsertionMethod, Expression.Default(targetCollectionElementType)),

                                                       Expression.Block
                                                       (
                                                           LookUpBlock(sourceCollectionLoopingVar, newElement, referenceTracker, mapper),
                                                           Expression.Call(targetCollection, targetCollectionInsertionMethod, newElement)
                                                       )
                                                   )
                                               )
                                               )));
        }
Exemple #12
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)
                                               ))
                   ));
        }