public IAstNode ProcessOperations()
		{
			var result = new AstComplexNode();
			foreach (var operation in operations)
			{
				IAstNode completeOperation = null;
				int operationId = AddObjectToStore(operation);

				if (operation is OperationsBlock)
				{
					completeOperation = 
						new MappingOperationsProcessor(this) 
						{ 
							operations = (operation as OperationsBlock).Operations 
						}.ProcessOperations();
				}
                else if (operation is ReadWriteComplex)
                {
                    completeOperation = Process_ReadWriteComplex(operation as ReadWriteComplex, operationId);
                }
                else if (operation is DestSrcReadOperation)
                {
                    completeOperation = ProcessDestSrcReadOperation(operation as DestSrcReadOperation, operationId);
                }
				else if (operation is SrcReadOperation)
				{
					completeOperation = ProcessSrcReadOperation(operation as SrcReadOperation, operationId);
				}
				else if (operation is DestWriteOperation)
				{
					completeOperation = ProcessDestWriteOperation(operation as DestWriteOperation, operationId);
				}
				else if (operation is ReadWriteSimple)
				{
					completeOperation = ProcessReadWriteSimple(operation as ReadWriteSimple, operationId);
				}

				if (completeOperation == null)
				{
					continue;
				}
				if (locException != null)
				{
					var tryCatch = CreateExceptionHandlingBlock(operationId, completeOperation);
					result.nodes.Add(tryCatch);
				}
				else
				{
					result.nodes.Add(completeOperation);
				}
			}
			return result;
		}
Beispiel #2
0
		public void BuildCopyImplMethod()
		{
			if (ReflectionUtils.IsNullable(from))
			{
				from = Nullable.GetUnderlyingType(from);
			}
			if (ReflectionUtils.IsNullable(to))
			{
				to = Nullable.GetUnderlyingType(to);
			}

			MethodBuilder methodBuilder = typeBuilder.DefineMethod(
				"MapImpl",
				MethodAttributes.Public | MethodAttributes.Virtual,
				typeof(object),
				new Type[] { typeof(object), typeof(object), typeof(object) }
				);

			ILGenerator ilGen = methodBuilder.GetILGenerator();
			CompilationContext compilationContext = new CompilationContext(ilGen);

			AstComplexNode mapperAst = new AstComplexNode();
			var locFrom = ilGen.DeclareLocal(from);
			var locTo = ilGen.DeclareLocal(to);
			var locState = ilGen.DeclareLocal(typeof(object));
			LocalBuilder locException = null;

			mapperAst.nodes.Add(BuilderUtils.InitializeLocal(locFrom, 1));
			mapperAst.nodes.Add(BuilderUtils.InitializeLocal(locTo, 2));
			mapperAst.nodes.Add(BuilderUtils.InitializeLocal(locState, 3));

#if DEBUG
			locException = compilationContext.ilGenerator.DeclareLocal(typeof(Exception));
#endif
			var mappingOperations = mappingConfigurator.GetMappingOperations(from, to);
			StaticConvertersManager staticConverter = mappingConfigurator.GetStaticConvertersManager();
            mapperAst.nodes.Add(
				new MappingOperationsProcessor()
				{
					locException = locException,
					locFrom = locFrom,
					locState = locState,
					locTo = locTo,
					objectsMapperManager = objectsMapperManager,
					compilationContext = compilationContext,
					storedObjects = storedObjects,
					operations = mappingOperations,
					mappingConfigurator = mappingConfigurator,
					rootOperation = mappingConfigurator.GetRootMappingOperation(from, to),
					staticConvertersManager = staticConverter ?? StaticConvertersManager.DefaultInstance
				}.ProcessOperations()
			);
			mapperAst.nodes.Add(
				new AstReturn()
				{
					returnType = typeof(object),
					returnValue = AstBuildHelper.ReadLocalRV(locTo)
				}
			);

			mapperAst.Compile(compilationContext);
		}
		private IAstNode Process_ReadWriteComplex_Copying(ReadWriteComplex op)
		{
			var result = new AstComplexNode();
			LocalBuilder origTempSrc, origTempDst;
			LocalBuilder tempSrc = compilationContext.ilGenerator.DeclareLocal(op.Source.MemberType);
			LocalBuilder tempDst = compilationContext.ilGenerator.DeclareLocal(op.Destination.MemberType);
			origTempSrc = tempSrc;
			origTempDst = tempDst;

			result.nodes.Add(
				new AstWriteLocal(tempSrc, AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadLocalRA(locFrom), op.Source.MembersChain)
				)
			);
			result.nodes.Add(
				new AstWriteLocal(tempDst, AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadLocalRA(locTo), op.Destination.MembersChain))
			);

			var writeNullToDest =
				new List<IAstNode>
                {
                    AstBuildHelper.WriteMembersChain(
                        op.Destination.MembersChain,
                        AstBuildHelper.ReadLocalRA(locTo),
                        GetNullValue(op.NullSubstitutor)
                    )
                };

			// Target construction
			var initDest = new List<IAstNode>();
			var custCtr = op.TargetConstructor;
			if (custCtr != null)
			{
				int custCtrIdx = AddObjectToStore(custCtr);
				initDest.Add(
					new AstWriteLocal(
						tempDst,
						AstBuildHelper.CallMethod(
							custCtr.GetType().GetMethod("Invoke"),
							GetStoredObject(custCtrIdx, custCtr.GetType()),
							null
						)
					)
				);
			}
			else
			{
				initDest.Add(
					new AstWriteLocal(tempDst, new AstNewObject(op.Destination.MemberType, null))
				);
			}

			var copying = new List<IAstNode>();

			// if destination is nullable, create a temp target variable with underlying destination type
			if (ReflectionUtils.IsNullable(op.Source.MemberType))
			{
				tempSrc = compilationContext.ilGenerator.DeclareLocal(Nullable.GetUnderlyingType(op.Source.MemberType));
				copying.Add(
					new AstWriteLocal(
						tempSrc,
						AstBuildHelper.ReadPropertyRV(
							AstBuildHelper.ReadLocalRA(origTempSrc),
							op.Source.MemberType.GetProperty("Value")
						)
					)
				);
			}

			// If destination is null, initialize it.
			if (ReflectionUtils.IsNullable(op.Destination.MemberType) || !op.Destination.MemberType.IsValueType)
			{
				copying.Add(
					new AstIf()
					{
						condition = ReflectionUtils.IsNullable(op.Destination.MemberType)
							? (IAstValue)new AstExprNot((IAstValue)AstBuildHelper.ReadPropertyRV(AstBuildHelper.ReadLocalRA(origTempDst), op.Destination.MemberType.GetProperty("HasValue")))
							: new AstExprIsNull(AstBuildHelper.ReadLocalRV(origTempDst)),
						trueBranch = new AstComplexNode() { nodes = initDest }
					}
				);
				if (ReflectionUtils.IsNullable(op.Destination.MemberType))
				{
					tempDst = compilationContext.ilGenerator.DeclareLocal(Nullable.GetUnderlyingType(op.Destination.MemberType));
					copying.Add(
						new AstWriteLocal(
							tempDst,
							AstBuildHelper.ReadPropertyRV(
								AstBuildHelper.ReadLocalRA(origTempDst),
								op.Destination.MemberType.GetProperty("Value")
							)
						)
					);
				}
			}

			// Suboperations
			copying.Add(
				new AstComplexNode()
				{
					nodes = new List<IAstNode> 
					{ 
						new MappingOperationsProcessor(this) 
						{ 
							operations = op.Operations, 
							locTo = tempDst, 
							locFrom = tempSrc,
							rootOperation = mappingConfigurator.GetRootMappingOperation(op.Source.MemberType, op.Destination.MemberType)
						}.ProcessOperations() 
					}
				}
			);

			IAstRefOrValue processedValue;
			if (ReflectionUtils.IsNullable(op.Destination.MemberType))
			{
				processedValue =
					new AstNewObject(
						op.Destination.MemberType,
						new[] 
                        {
                            AstBuildHelper.ReadLocalRV(tempDst)
                        }
					);
			}
			else
			{
				processedValue = AstBuildHelper.ReadLocalRV(origTempDst);
			}

			if (op.ValuesPostProcessor != null)
			{
				int postProcessorId = AddObjectToStore(op.ValuesPostProcessor);
				processedValue =
					AstBuildHelper.CallMethod(
						op.ValuesPostProcessor.GetType().GetMethod("Invoke"),
						GetStoredObject(postProcessorId, op.ValuesPostProcessor.GetType()),
						new List<IAstStackItem>
                        {
                            processedValue,
                            AstBuildHelper.ReadLocalRV(locState)
                        }
					);
			}

			copying.Add(
				AstBuildHelper.WriteMembersChain(
					op.Destination.MembersChain,
					AstBuildHelper.ReadLocalRA(locTo),
					processedValue
				)
			);

			if (ReflectionUtils.IsNullable(op.Source.MemberType) || !op.Source.MemberType.IsValueType)
			{
				result.nodes.Add(
					new AstIf()
					{
						condition = ReflectionUtils.IsNullable(op.Source.MemberType)
							? (IAstValue)new AstExprNot((IAstValue)AstBuildHelper.ReadPropertyRV(AstBuildHelper.ReadLocalRA(origTempSrc), op.Source.MemberType.GetProperty("HasValue")))
							: new AstExprIsNull(AstBuildHelper.ReadLocalRV(origTempSrc)),
						trueBranch = new AstComplexNode() { nodes = writeNullToDest },
						falseBranch = new AstComplexNode() { nodes = copying }
					}
				);
			}
			else
			{
				result.nodes.AddRange(copying);
			}
			return result;
		}
		private IAstNode Process_ValuesFilter(
			IReadWriteOperation op, 
			int operationId, 
			IAstNode result, 
			IAstRefOrValue value, 
			string fieldName,
			Delegate filterDelegate
		)
		{
			result = new AstComplexNode
			{
				nodes = new List<IAstNode>
					{
						new AstIf
						{
							condition = (IAstValue)AstBuildHelper.CallMethod(
								filterDelegate.GetType().GetMethod("Invoke"),
								new AstCastclassRef(
									(IAstRef)AstBuildHelper.ReadMemberRV(
										 GetStoredObject(operationId, typeof(IReadWriteOperation)),
										 typeof(IReadWriteOperation).GetProperty(fieldName)
									),
									filterDelegate.GetType()
								),
								new List<IAstStackItem>()
								{
									value,
									AstBuildHelper.ReadLocalRV(locState),
								}
							),
							trueBranch = new AstComplexNode{ nodes = new List<IAstNode> { result } }
						}
					}
			};
			return result;
		}