/// <summary>
        ///     <para>
        ///         Uses any available <see cref="ValueConverter" /> to help find a mapping that works.
        ///     </para>
        ///     <para>
        ///         Note: providers should typically not need to override this method.
        ///     </para>
        /// </summary>
        /// <param name="mappingInfo"> The mapping info. </param>
        /// <returns> The type mapping with conversions applied, or <c>null</c> if none could be found. </returns>
        protected virtual CoreTypeMapping FindMappingWithConversion([NotNull] TypeMappingInfo mappingInfo)
        {
            Check.NotNull(mappingInfo, nameof(mappingInfo));

            return(_explicitMappings.GetOrAdd(
                       mappingInfo,
                       k =>
            {
                var principals = mappingInfo.Property?.FindPrincipals().ToList();

                var customConverter = principals
                                      ?.Select(p => p.GetValueConverter())
                                      .FirstOrDefault(c => c != null);

                if (customConverter != null)
                {
                    mappingInfo = mappingInfo.WithConverter(
                        new ValueConverterInfo(
                            customConverter.ModelClrType,
                            customConverter.ProviderClrType,
                            i => customConverter,
                            customConverter.MappingHints));
                }

                var providerClrType = principals
                                      ?.Select(p => p.GetProviderClrType())
                                      .FirstOrDefault(t => t != null)
                                      ?.UnwrapNullableType();

                var mapping = providerClrType == null ||
                              providerClrType == mappingInfo.ClrType
                        ? FindMapping(mappingInfo)
                        : null;

                if (mapping == null)
                {
                    var sourceType = mappingInfo.ClrType;

                    if (sourceType != null)
                    {
                        foreach (var converterInfo in Dependencies
                                 .ValueConverterSelector
                                 .Select(sourceType, providerClrType))
                        {
                            var mappingInfoUsed = mappingInfo.WithConverter(converterInfo);
                            mapping = FindMapping(mappingInfoUsed);

                            if (mapping == null &&
                                providerClrType != null)
                            {
                                foreach (var secondConverterInfo in Dependencies
                                         .ValueConverterSelector
                                         .Select(providerClrType))
                                {
                                    mapping = FindMapping(mappingInfoUsed.WithConverter(secondConverterInfo));

                                    if (mapping != null)
                                    {
                                        mapping = mapping.Clone(secondConverterInfo.Create());
                                        break;
                                    }
                                }
                            }

                            if (mapping != null)
                            {
                                mapping = mapping.Clone(converterInfo.Create());
                                break;
                            }
                        }
                    }
                }

                if (mapping != null &&
                    customConverter != null)
                {
                    mapping = mapping.Clone(customConverter);
                }

                return mapping;
            }));
        }
Beispiel #2
0
        private CoreTypeMapping FindMappingWithConversion(
            TypeMappingInfo mappingInfo,
            [CanBeNull] IProperty property)
        {
            Check.NotNull(mappingInfo, nameof(mappingInfo));

            var principals = property?.FindPrincipals().ToList();

            var customConverter = principals
                                  ?.Select(p => p.GetValueConverter())
                                  .FirstOrDefault(c => c != null);

            var providerClrType = principals
                                  ?.Select(p => p.GetProviderClrType())
                                  .FirstOrDefault(t => t != null)
                                  ?.UnwrapNullableType();

            var resolvedMapping = _explicitMappings.GetOrAdd(
                mappingInfo,
                k =>
            {
                var mapping = providerClrType == null ||
                              providerClrType == mappingInfo.ClrType
                        ? FindMapping(mappingInfo)
                        : null;

                if (mapping == null)
                {
                    var sourceType = mappingInfo.ClrType;

                    if (sourceType != null)
                    {
                        foreach (var converterInfo in Dependencies
                                 .ValueConverterSelector
                                 .Select(sourceType, providerClrType))
                        {
                            var mappingInfoUsed = mappingInfo.WithConverter(converterInfo);
                            mapping             = FindMapping(mappingInfoUsed);

                            if (mapping == null &&
                                providerClrType != null)
                            {
                                foreach (var secondConverterInfo in Dependencies
                                         .ValueConverterSelector
                                         .Select(providerClrType))
                                {
                                    mapping = FindMapping(mappingInfoUsed.WithConverter(secondConverterInfo));

                                    if (mapping != null)
                                    {
                                        mapping = mapping.Clone(secondConverterInfo.Create());
                                        break;
                                    }
                                }
                            }

                            if (mapping != null)
                            {
                                mapping = mapping.Clone(converterInfo.Create());
                                break;
                            }
                        }
                    }
                }

                if (mapping != null &&
                    customConverter != null)
                {
                    mapping = mapping.Clone(customConverter);
                }

                return(mapping);
            });

            ValidateMapping(resolvedMapping, property);

            return(resolvedMapping);
        }