Example #1
0
        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);
        }