public APrivateMap() { var options = new AutoMapOptions { IncludePrivateMembers = true, MemberTypes = MemberTypes.Fields }; AutoMap(options); }
/// <summary> /// Auto maps all properties/fields for the given type. If a property/field /// is mapped again it will override the existing map. /// </summary> /// <param name="options">Options for auto mapping.</param> public virtual void AutoMap( AutoMapOptions options ) { var mapParents = new LinkedList<Type>(); AutoMapInternal( this, options, mapParents ); }
/// <summary> /// Auto maps the given map and checks for circular references as it goes. /// </summary> /// <param name="map">The map to auto map.</param> /// <param name="options">Options for auto mapping.</param> /// <param name="mapParents">The list of parents for the map.</param> /// <param name="indexStart">The index starting point.</param> internal static void AutoMapInternal( CsvClassMap map, AutoMapOptions options, LinkedList<Type> mapParents, int indexStart = 0 ) { var type = map.GetType().GetTypeInfo().BaseType.GetGenericArguments()[0]; if( typeof( IEnumerable ).IsAssignableFrom( type ) ) { throw new CsvConfigurationException( "Types that inherit IEnumerable cannot be auto mapped. " + "Did you accidentally call GetRecord or WriteRecord which " + "acts on a single record instead of calling GetRecords or " + "WriteRecords which acts on a list of records?" ); } var flags = BindingFlags.Instance | BindingFlags.Public; if( options.IncludePrivateProperties ) { flags = flags | BindingFlags.NonPublic; } var members = new List<MemberInfo>(); if( ( options.MemberTypes & MemberTypes.Properties ) == MemberTypes.Properties ) { var properties = type.GetProperties( flags ); members.AddRange( properties ); } if( ( options.MemberTypes & MemberTypes.Fields ) == MemberTypes.Fields ) { var fields = new List<MemberInfo>(); foreach( var field in type.GetFields( flags ) ) { if( !field.GetCustomAttributes( typeof( CompilerGeneratedAttribute ), false ).Any() ) { fields.Add( field ); } } members.AddRange( fields ); } foreach( var member in members ) { var typeConverterType = TypeConverterFactory.GetConverter( member.MemberType() ).GetType(); if( typeConverterType == typeof( EnumerableConverter ) ) { // The IEnumerable converter just throws an exception so skip it. continue; } var isDefaultConverter = typeConverterType == typeof( DefaultTypeConverter ); var hasDefaultConstructor = member.MemberType().GetConstructor( new Type[0] ) != null; if( isDefaultConverter && hasDefaultConstructor ) { if( options.IgnoreReferences ) { continue; } // If the type is not one covered by our type converters // and it has a parameterless constructor, create a // reference map for it. if( CheckForCircularReference( member.MemberType(), mapParents ) ) { continue; } mapParents.AddLast( type ); var refMapType = typeof( DefaultCsvClassMap<> ).MakeGenericType( member.MemberType() ); var refMap = (CsvClassMap)ReflectionHelper.CreateInstance( refMapType ); var refOptions = options.Copy(); refOptions.IgnoreReferences = false; AutoMapInternal( refMap, options, mapParents, map.GetMaxIndex() + 1 ); if( refMap.PropertyMaps.Count > 0 || refMap.ReferenceMaps.Count > 0 ) { var referenceMap = new CsvPropertyReferenceMap( member, refMap ); if( options.PrefixReferenceHeaders ) { referenceMap.Prefix(); } map.ReferenceMaps.Add( referenceMap ); } } else { var propertyMap = new CsvPropertyMap( member ); // Use global values as the starting point. propertyMap.Data.TypeConverterOptions = TypeConverterOptions.Merge( options.TypeConverterOptionsFactory.GetOptions( member.MemberType() ) ); propertyMap.Data.Index = map.GetMaxIndex() + 1; if( !isDefaultConverter ) { // Only add the property/field map if it can be converted later on. // If the property/field will use the default converter, don't add it because // we don't want the .ToString() value to be used when auto mapping. map.PropertyMaps.Add( propertyMap ); } } } map.ReIndex( indexStart ); }