/// <summary> /// This will throw an exception if unable to generate a converter for request TSource and TDest pair, it will never return null /// </summary> public static ICompilableTypeConverter <TSource, TDest> GetConverter <TSource, TDest>( IEnumerable <PropertyInfo> propertiesToIgnoreIfSettingPropertiesOnTDest, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { if (propertiesToIgnoreIfSettingPropertiesOnTDest == null) { throw new ArgumentNullException("propertiesToIgnoreIfSettingPropertiesOnTDest"); } var propertiesToIgnoreList = propertiesToIgnoreIfSettingPropertiesOnTDest.ToList(); if (propertiesToIgnoreList.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in propertiesToIgnoreIfSettingPropertiesOnTDest set "); } if (!Enum.IsDefined(typeof(ConverterOverrideBehaviourOptions), converterOverrideBehaviour)) { throw new ArgumentOutOfRangeException("converterOverrideBehaviour"); } lock (_lock) { // Note: new PropertyInfo[0] is always passed for initialisedFlagsIfTranslatingNullsToEmptyInstances for since this // wrapper always specifies ByPropertySettingNullSourceBehaviourOptions.UseDestDefaultIfSourceIsNull and the // initialised-instance flags are only applicable to the CreateEmptyInstanceWithDefaultPropertyValues // ByPropertySettingNullSourceBehaviourOptions configuration return(_converter.GetConverter <TSource, TDest>( propertiesToIgnoreIfSettingPropertiesOnTDest, new PropertyInfo[0], // ByPropertySettingNullSourceBehaviourOptions.UseDestDefaultIfSourceIsNull converterOverrideBehaviour )); } }
/// <summary> /// This will throw an exception if unable to generate the requested mapping. If successful, the returned converter /// factory will be able to convert instances of TSource to TDest instances. It may also use this conversion knowledge /// when generating later conversions - eg. if CreateMap is subsequently called for TSource2 ant TDest2, where TSource /// has a property TSource that must be mapped to a property on TDest2 of type TDest, this new converter may be used /// there. If TSource2's property is of type IEnumerable TSource, and must be mapped to a property on TDest2 of type /// IEnumerable TDest, this will also be handled using this new converter. For most cases, this method is only necessary /// for such sub types - to convert from one type to another where all of the properties are primitives, the Convert and /// TryToGetConverter methods may be called without any prior CreateMap calls. If nested types are in the source or /// destination types then CreateMap needs to be called for them. Where there are deeply-nested types for conversion, /// CreateMap should be called from the deepest level and worked up to the top. /// </summary> public static void CreateMap <TSource, TDest>( IEnumerable <PropertyInfo> propertiesToIgnoreIfSettingPropertiesOnTDest, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { // This is just a wrapper around GetConverter for when you don't immediately care about the generated // converter, you just need to build up some mappings GetConverter <TSource, TDest>(propertiesToIgnoreIfSettingPropertiesOnTDest, converterOverrideBehaviour); }
/// <summary> /// Create a new target type instance from a source value - this will throw an exception if conversion fails /// </summary> public static TDest Convert <TSource, TDest>( TSource source, IEnumerable <PropertyInfo> propertiesToIgnoreIfSettingPropertiesOnTDest, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { // This is also a wrapper around GetConverter to make it easy for callers to get going (for performance reasons, // it would be best to call GetConverter from the caller and store the converter reference somewhere since that // would avoid the lock around each request that the GetConverter method requires). return(GetConverter <TSource, TDest>(propertiesToIgnoreIfSettingPropertiesOnTDest, converterOverrideBehaviour).Convert(source)); }
public static IEnumerable <TDest> Convert <TSource, TDest>( IEnumerable <TSource> source, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { if (source == null) { return(null); } return(source.Select(value => Convert <TSource, TDest>(value, converterOverrideBehaviour))); }
public static IEnumerable <TDest> Convert <TSource, TDest>( IEnumerable <TSource> source, IEnumerable <PropertyInfo> propertiesToIgnoreIfSettingPropertiesOnTDest, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { if (source == null) { return(null); } return(source.Select(value => Convert <TSource, TDest>(value, propertiesToIgnoreIfSettingPropertiesOnTDest, converterOverrideBehaviour))); }
public static TDest Convert <TSource, TDest>( TSource source, ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { return(Convert <TSource, TDest>(source, new PropertyInfo[0], converterOverrideBehaviour)); }
public static void CreateMap <TSource, TDest>( ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { CreateMap <TSource, TDest>(new PropertyInfo[0], converterOverrideBehaviour); }
public static ICompilableTypeConverter <TSource, TDest> GetConverter <TSource, TDest>( ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { return(GetConverter <TSource, TDest>(new PropertyInfo[0], converterOverrideBehaviour)); }
/// <summary> /// This will throw an exception if unable to generate a converter for request TSource and TDest pair, it will never return null /// </summary> public ICompilableTypeConverter <TSource, TDest> GetConverter <TSource, TDest>( IEnumerable <PropertyInfo> propertiesToIgnoreIfSettingPropertiesOnTDest, IEnumerable <PropertyInfo> initialisedFlagsIfTranslatingNullsToEmptyInstances, ConverterOverrideBehaviourOptions converterOverrideBehaviour) { if (propertiesToIgnoreIfSettingPropertiesOnTDest == null) { throw new ArgumentNullException("propertiesToIgnoreIfSettingPropertiesOnTDest"); } var propertiesToIgnoreList = propertiesToIgnoreIfSettingPropertiesOnTDest.ToList(); if (propertiesToIgnoreList.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in propertiesToIgnoreIfSettingPropertiesOnTDest set "); } if (initialisedFlagsIfTranslatingNullsToEmptyInstances == null) { throw new ArgumentNullException("initialisedFlagsIfTranslatingNullsToEmptyInstances"); } var initialisedFlagsIfTranslatingNullsToEmptyInstancesList = initialisedFlagsIfTranslatingNullsToEmptyInstances.ToList(); if (initialisedFlagsIfTranslatingNullsToEmptyInstances.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in initialisedFlagsIfTranslatingNullsToEmptyInstances set "); } if (!Enum.IsDefined(typeof(ConverterOverrideBehaviourOptions), converterOverrideBehaviour)) { throw new ArgumentOutOfRangeException("converterOverrideBehaviour"); } var cacheKey = Tuple.Create(typeof(TSource), typeof(TDest)); if (converterOverrideBehaviour != ConverterOverrideBehaviourOptions.IgnoreCache) { object unTypedCachedResult; if (_converterCache.TryGetValue(cacheKey, out unTypedCachedResult)) { if (converterOverrideBehaviour == ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { return((ICompilableTypeConverter <TSource, TDest>)unTypedCachedResult); } _converterCache.Remove(cacheKey); } } // If there are any properties-to-ignore specified then add them to the total combined list and re-generate the // _propertySetterBasedConverterFactory reference to take them into account. Also add any initialised-flags to the ignore list // since these are not expected to be mapped from the source data, these flags are expected to be set afterwards (with false // if the source reference was null and true if not) if (propertiesToIgnoreList.Any() || initialisedFlagsIfTranslatingNullsToEmptyInstances.Any()) { _allPropertiesToIgnoreToPropertySetterConversions.AddRange(propertiesToIgnoreIfSettingPropertiesOnTDest); _allPropertiesToIgnoreToPropertySetterConversions.AddRange(initialisedFlagsIfTranslatingNullsToEmptyInstances); _allInitialisedFlagsIfTranslatingNullsToEmptyInstances.AddRange(initialisedFlagsIfTranslatingNullsToEmptyInstances); var currentByPropertySetterConvererFactoryConfigurationData = _propertySetterBasedConverterFactory.GetConfigurationData(); _propertySetterBasedConverterFactory = new ExtendableCompilableTypeConverterFactory( currentByPropertySetterConvererFactoryConfigurationData.NameMatcher, currentByPropertySetterConvererFactoryConfigurationData.BasePropertyGetterFactories, propertyGetterFactories => new CompilableTypeConverterByPropertySettingFactory( new CombinedCompilablePropertyGetterFactory(propertyGetterFactories), CompilableTypeConverterByPropertySettingFactory.PropertySettingTypeOptions.MatchAll, _allPropertiesToIgnoreToPropertySetterConversions, _nullSourceBehaviour, _allInitialisedFlagsIfTranslatingNullsToEmptyInstances ), currentByPropertySetterConvererFactoryConfigurationData.PropertyGetterFactoryExtrapolator ); } // Attempt to generate a converter using the _constructorBasedConverterFactory and then the _propertySetterBasedConverterFactory. // If both fail then it's difficult to know for sure which exception is most useful to allow through. If the destination type has // a parameter-less constructor then allow the by-property-setter exception to be raised (if there was no parameter-less constructor // then the by-property-setter factory wouldn't have been able to do anything and we'll assume that the by-constructor factory // exception is more useful). ICompilableTypeConverter <TSource, TDest> converter; Exception mappingException; try { converter = _constructorBasedConverterFactory.Get <TSource, TDest>(); } catch (Exception byConstructorException) { try { converter = _propertySetterBasedConverterFactory.Get <TSource, TDest>(); } catch (Exception byPropertySettingException) { if (typeof(TDest).GetConstructor(new Type[0]) != null) { mappingException = byPropertySettingException; } else { mappingException = byConstructorException; } throw mappingException; } } _constructorBasedConverterFactory = _constructorBasedConverterFactory.AddNewConverter(converter); _propertySetterBasedConverterFactory = _propertySetterBasedConverterFactory.AddNewConverter(converter); if (converterOverrideBehaviour != ConverterOverrideBehaviourOptions.IgnoreCache) { _converterCache[cacheKey] = converter; } return(converter); }
/// <summary> /// This will throw an exception if a converter for the TSource, TDest could not be created /// </summary> public void Create(ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter) { Converter.CreateMap <TSource, TDest>(_propertiesToIgnore, converterOverrideBehaviour); }