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