/// <summary> /// This will return an ExtendableCompilableTypeConverterFactory based around the destination types having a zero parameter constructor and /// its data being set through public properties /// </summary> public static ExtendableCompilableTypeConverterFactory GeneratePropertySetterBasedFactory( INameMatcher nameMatcher, CompilableTypeConverterByPropertySettingFactory.PropertySettingTypeOptions propertySettingTypeOptions, IEnumerable <ICompilablePropertyGetterFactory> basePropertyGetterFactories, IEnumerable <PropertyInfo> propertiesToIgnore, ByPropertySettingNullSourceBehaviourOptions nullSourceBehaviour, IEnumerable <PropertyInfo> initialisedFlagsIfTranslatingNullsToEmptyInstances, EnumerableSetNullHandlingOptions enumerableSetNullHandling) { if (nameMatcher == null) { throw new ArgumentNullException("nameMatcher"); } if (!Enum.IsDefined(typeof(CompilableTypeConverterByPropertySettingFactory.PropertySettingTypeOptions), propertySettingTypeOptions)) { throw new ArgumentOutOfRangeException("propertySettingTypeOptions"); } if (basePropertyGetterFactories == null) { throw new ArgumentNullException("basePropertyGetterFactories"); } if (propertiesToIgnore == null) { throw new ArgumentNullException("propertiesToIgnore"); } if (initialisedFlagsIfTranslatingNullsToEmptyInstances == null) { throw new ArgumentNullException("initialisedFlagsIfTranslatingNullsToEmptyInstances"); } if (!Enum.IsDefined(typeof(ByPropertySettingNullSourceBehaviourOptions), nullSourceBehaviour)) { throw new ArgumentOutOfRangeException("nullSourceBehaviour"); } if (!Enum.IsDefined(typeof(EnumerableSetNullHandlingOptions), enumerableSetNullHandling)) { throw new ArgumentOutOfRangeException("enumerableSetNullHandling"); } return(new ExtendableCompilableTypeConverterFactory( nameMatcher, basePropertyGetterFactories, propertyGetterFactories => new CompilableTypeConverterByPropertySettingFactory( // Define a ConverterFactoryGenerator to return a CompilableTypeConverterByPropertySettingFactory when new conversions are registered new CombinedCompilablePropertyGetterFactory(propertyGetterFactories), propertySettingTypeOptions, propertiesToIgnore, nullSourceBehaviour, initialisedFlagsIfTranslatingNullsToEmptyInstances ), new CompilableTypeConverterPropertyGetterFactoryExtrapolator( nameMatcher, enumerableSetNullHandling ) )); }
public CompilableTypeConverterByPropertySettingFactory( ICompilablePropertyGetterFactory propertyGetterFactory, PropertySettingTypeOptions propertySettingType, IEnumerable <PropertyInfo> propertiesToIgnore, ByPropertySettingNullSourceBehaviourOptions nullSourceBehaviour, IEnumerable <PropertyInfo> initialisedFlagsIfTranslatingNullsToEmptyInstances) { if (propertyGetterFactory == null) { throw new ArgumentNullException("propertyGetterFactory"); } if (!Enum.IsDefined(typeof(PropertySettingTypeOptions), propertySettingType)) { throw new ArgumentOutOfRangeException("propertySettingType"); } if (propertiesToIgnore == null) { throw new ArgumentNullException("propertiesToIgnore"); } if (!Enum.IsDefined(typeof(ByPropertySettingNullSourceBehaviourOptions), nullSourceBehaviour)) { throw new ArgumentOutOfRangeException("nullSourceBehaviour"); } if (initialisedFlagsIfTranslatingNullsToEmptyInstances == null) { throw new ArgumentNullException("initialisedFlagsIfTranslatingNullsToEmptyInstances"); } if ((nullSourceBehaviour != ByPropertySettingNullSourceBehaviourOptions.CreateEmptyInstanceWithDefaultPropertyValues) && initialisedFlagsIfTranslatingNullsToEmptyInstances.Any()) { throw new ArgumentException("initialisedFlagsIfTranslatingNullsToEmptyInstances must be empty if nullSourceBehaviour is not CreateEmptyInstanceWithDefaultPropertyValues"); } _propertyGetterFactory = propertyGetterFactory; _propertySettingType = propertySettingType; _propertiesToIgnore = new HashSet <PropertyInfo>(propertiesToIgnore); if (_propertiesToIgnore.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in propertiesToIgnore set"); } _nullSourceBehaviour = nullSourceBehaviour; _initialisedFlagsIfTranslatingNullsToEmptyInstances = initialisedFlagsIfTranslatingNullsToEmptyInstances.ToList().AsReadOnly(); if (_initialisedFlagsIfTranslatingNullsToEmptyInstances.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in initialisedFlagsIfTranslatingNullToEmptyInstance set"); } if (_initialisedFlagsIfTranslatingNullsToEmptyInstances.Any(p => (p.PropertyType != typeof(bool)) && (p.PropertyType != typeof(bool?)))) { throw new ArgumentException("Encountered invalid property in initialisedFlagsIfTranslatingNullToEmptyInstance set, PropertyType must be bool or nullable bool"); } }
public ConverterWrapper(ByPropertySettingNullSourceBehaviourOptions nullSourceBehaviour, EnumerableSetNullHandlingOptions enumerableSetNullHandling) { if (!Enum.IsDefined(typeof(ByPropertySettingNullSourceBehaviourOptions), nullSourceBehaviour)) { throw new ArgumentOutOfRangeException("nullSourceBehaviour"); } if (!Enum.IsDefined(typeof(EnumerableSetNullHandlingOptions), enumerableSetNullHandling)) { throw new ArgumentOutOfRangeException("enumerableSetNullHandling"); } _nullSourceBehaviour = nullSourceBehaviour; _enumerableSetNullHandling = enumerableSetNullHandling; _allPropertiesToIgnoreToPropertySetterConversions = new List <PropertyInfo>(); _allInitialisedFlagsIfTranslatingNullsToEmptyInstances = new List <PropertyInfo>(); _converterCache = new Dictionary <Tuple <Type, Type>, object>(); // Prepare converter factories (for by-constructor and by-property-setters) using the base types (AssignableType and // EnumConversion property getter factories) var nameMatcher = new CaseInsensitiveSkipUnderscoreNameMatcher(); var basePropertyGetterFactories = new ICompilablePropertyGetterFactory[] { new CompilableAssignableTypesPropertyGetterFactory(nameMatcher), new CompilableEnumConversionPropertyGetterFactory(nameMatcher) }; _constructorBasedConverterFactory = ExtendableCompilableTypeConverterFactoryHelpers.GenerateConstructorBasedFactory( nameMatcher, new ArgsLengthTypeConverterPrioritiserFactory(), basePropertyGetterFactories, _enumerableSetNullHandling ); _propertySetterBasedConverterFactory = ExtendableCompilableTypeConverterFactoryHelpers.GeneratePropertySetterBasedFactory( nameMatcher, CompilableTypeConverterByPropertySettingFactory.PropertySettingTypeOptions.MatchAll, basePropertyGetterFactories, _allPropertiesToIgnoreToPropertySetterConversions, _nullSourceBehaviour, _allInitialisedFlagsIfTranslatingNullsToEmptyInstances, _enumerableSetNullHandling ); }
public CompilableTypeConverterByPropertySetting( IEnumerable <ICompilablePropertyGetter> propertyGetters, IEnumerable <PropertyInfo> propertiesToSet, ByPropertySettingNullSourceBehaviourOptions nullSourceBehaviour, IEnumerable <PropertyInfo> initialisedFlagsIfTranslatingNullToEmptyInstance) { if (propertyGetters == null) { throw new ArgumentNullException("propertyGetters"); } if (propertiesToSet == null) { throw new ArgumentNullException("propertiesToSet"); } if (!Enum.IsDefined(typeof(ByPropertySettingNullSourceBehaviourOptions), nullSourceBehaviour)) { throw new ArgumentOutOfRangeException("nullSourceBehaviour"); } if (initialisedFlagsIfTranslatingNullToEmptyInstance == null) { throw new ArgumentNullException("initialisedFlagsIfTranslatingNullToEmptyInstance"); } if ((nullSourceBehaviour != ByPropertySettingNullSourceBehaviourOptions.CreateEmptyInstanceWithDefaultPropertyValues) && initialisedFlagsIfTranslatingNullToEmptyInstance.Any()) { throw new ArgumentException("initialisedFlagsIfTranslatingNullToEmptyInstance must be empty if nullSourceBehaviour is not CreateEmptyInstanceWithDefaultPropertyValues"); } // Ensure there are no null references in the property lists var propertyGettersList = new List <ICompilablePropertyGetter>(); foreach (var propertyGetter in propertyGetters) { if (propertyGetter == null) { throw new ArgumentException("Null reference encountered in propertyGetters list"); } if (!propertyGetter.SrcType.Equals(typeof(TSource))) { throw new ArgumentException("Encountered invalid SrcType in propertyGetters list, must match type param TSource"); } propertyGettersList.Add(propertyGetter); } var propertiesToSetList = new List <PropertyInfo>(); foreach (var property in propertiesToSet) { if (property == null) { throw new ArgumentException("Null reference encountered in propertyGetters list"); } if (!typeof(TDest).HasProperty(property)) { throw new ArgumentException("Encountered invalid entry in propertiesToSete set, not available on type TDest"); } propertiesToSetList.Add(property); } // Ensure that the property getters correspond to the target properties if (propertyGettersList.Count != propertiesToSetList.Count) { throw new ArgumentException("Number of propertyGetters specified must match number of propertiesToSet"); } for (var index = 0; index < propertyGettersList.Count; index++) { if (!propertiesToSetList[index].PropertyType.IsAssignableFrom(propertyGettersList[index].TargetType)) { throw new ArgumentException("propertyGetter[" + index + "].TargetType is not assignable to corresponding propertyToSet"); } } _propertyGetters = propertyGettersList.AsReadOnly(); _propertiesToSet = propertiesToSetList.AsReadOnly(); _nullSourceBehaviour = nullSourceBehaviour; _initialisedFlagsIfTranslatingNullToEmptyInstance = initialisedFlagsIfTranslatingNullToEmptyInstance.ToList().AsReadOnly(); if (_initialisedFlagsIfTranslatingNullToEmptyInstance.Any(p => p == null)) { throw new ArgumentException("Null reference encountered in initialisedFlagsIfTranslatingNullToEmptyInstance set"); } if (_initialisedFlagsIfTranslatingNullToEmptyInstance.Any(p => (p.PropertyType != typeof(bool)) && (p.PropertyType != typeof(bool?)))) { throw new ArgumentException("Encountered invalid property in initialisedFlagsIfTranslatingNullToEmptyInstance set, PropertyType must be bool or nullable bool"); } if (_initialisedFlagsIfTranslatingNullToEmptyInstance.Any(p => !typeof(TDest).HasProperty(p))) { throw new ArgumentException("Encountered invalid property in initialisedFlagsIfTranslatingNullToEmptyInstance set, must be a property available on TDest"); } PropertyMappings = propertyGettersList .Select((sourceProperty, index) => new PropertyMappingDetails( sourceProperty.Property, propertiesToSetList[index].Name, propertiesToSetList[index].PropertyType )); // Generate a Expression<Func<TSource, TDest>>, the _rawConverterExpression is still required for the GetTypeConverterExpression // method (this may be called to retrieve the raw expression, rather than the Func-wrapped version - eg. by the ListCompilablePropertyGetter, // which has a set of TSource objects and wants to translate them into a set of TDest objects) var srcParameter = Expression.Parameter(typeof(TSource), "src"); _converterFuncExpression = Expression.Lambda <Func <TSource, TDest> >( GetTypeConverterExpression(srcParameter), srcParameter ); // Compile the expression into an actual Func<TSource, TDest> (this is expected to be the most commonly-used form of the data) _converter = _converterFuncExpression.Compile(); }