private static TDestination Adapt(TSource source, TDestination destination, bool isNew, bool evaluateMaxDepth, Dictionary <long, int> parameterIndexes) { if (source == null) { return(default(TDestination)); } var configSettings = TypeAdapterConfig <TSource, TDestination> .ConfigSettings; bool hasConfig = false; bool hasMaxDepth = false; if (configSettings != null) { hasConfig = true; if (configSettings.ConverterFactory != null) { var converter = configSettings.ConverterFactory(); return(converter.Resolve(source)); } int maxDepth = configSettings.MaxDepth.GetValueOrDefault(); if (maxDepth > 0) { hasMaxDepth = true; if (MaxDepthExceeded(ref parameterIndexes, maxDepth, evaluateMaxDepth)) { return(default(TDestination)); } } } if (destination == null) { destination = DestinationFactory(); } bool ignoreNullValues = isNew || (hasConfig && configSettings.IgnoreNullValues.HasValue && configSettings.IgnoreNullValues.Value); PropertyModel <TSource, TDestination> propertyModel = null; try { var propertyModels = GetAdapterModel().Properties; for (int index = 0; index < propertyModels.Length; index++) { propertyModel = propertyModels[index]; object destinationValue = null; switch (propertyModel.ConvertType) { case 1: //Primitive object primitiveValue = propertyModel.Getter.Invoke(source); if (primitiveValue == null) { continue; } if (propertyModel.AdaptInvoker == null) { destinationValue = primitiveValue; } else { destinationValue = propertyModel.AdaptInvoker(null, new[] { primitiveValue, true, (hasMaxDepth ? ReflectionUtils.Clone(parameterIndexes) : parameterIndexes) }); } break; case 2: //Flattening Get Method destinationValue = propertyModel.AdaptInvoker(source, null); break; case 3: //Flattening Deep Property var flatInvokers = propertyModel.FlatteningInvokers; object value = source; foreach (GenericGetter getter in flatInvokers) { value = getter.Invoke(value); if (value == null) { break; } } if (value == null && ignoreNullValues) { continue; } destinationValue = value; break; case 4: // Adapter object sourceValue = propertyModel.Getter.Invoke(source); if (sourceValue == null && ignoreNullValues) { continue; } destinationValue = propertyModel.AdaptInvoker(null, new[] { sourceValue, true, (hasMaxDepth ? ReflectionUtils.Clone(parameterIndexes) : parameterIndexes) }); break; case 5: // Custom Resolve if (propertyModel.Condition == null || propertyModel.Condition(source)) { destinationValue = propertyModel.CustomResolver(source); break; } continue; } if (propertyModel.DestinationTransform == null) { propertyModel.Setter.Invoke(destination, destinationValue); } else { propertyModel.Setter.Invoke(destination, propertyModel.DestinationTransform(destinationValue)); } } } catch (Exception ex) { if (ex is ArgumentOutOfRangeException) { throw; } if (_adapterModel == null) { throw new InvalidOperationException(_nonInitializedAdapterMessage + "\nException: " + ex); } if (propertyModel != null) { //Todo: This slows things down with the try-catch but the information is critical in debugging throw new InvalidOperationException(_propertyMappingErrorMessage + propertyModel.SetterPropertyName + "\nException: " + ex, ex); } throw; } return(destination); }