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