コード例 #1
0
        /// <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
                           ));
            }
        }
コード例 #2
0
 /// <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);
 }
コード例 #3
0
 /// <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));
 }
コード例 #4
0
        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)));
        }
コード例 #5
0
        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)));
        }
コード例 #6
0
 public static TDest Convert <TSource, TDest>(
     TSource source,
     ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter)
 {
     return(Convert <TSource, TDest>(source, new PropertyInfo[0], converterOverrideBehaviour));
 }
コード例 #7
0
 public static void CreateMap <TSource, TDest>(
     ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter)
 {
     CreateMap <TSource, TDest>(new PropertyInfo[0], converterOverrideBehaviour);
 }
コード例 #8
0
 public static ICompilableTypeConverter <TSource, TDest> GetConverter <TSource, TDest>(
     ConverterOverrideBehaviourOptions converterOverrideBehaviour = ConverterOverrideBehaviourOptions.UseAnyExistingConverter)
 {
     return(GetConverter <TSource, TDest>(new PropertyInfo[0], converterOverrideBehaviour));
 }
コード例 #9
0
        /// <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);
        }
コード例 #10
0
 /// <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);
 }