<commit_before>##Fpr - The Mapper of Your Domain

A fast, fun and stimulating object to object mapper for .Net 4.5.  

Fpr was originally forked from FastMapper (https://fmapper.codeplex.com/).
Fpr maps properties by convention, including nested complex objects and collections, but also supports
explicit mapping.

This fork fixes some issues and includes some additions to make the mapper more configurable and useful for .Net 4.5:

* Support for IReadOnlyList
* Mapping of members with non-public setters
* Automatic mapping of nullable primitives to non-nullable primitives
* Improved error messages that help you find configuration errors
* Conditional mapping
* Assembly scanning for custom mappers
* Strict modes to err if types or members are not explicity mapped (implicit/forgiving mapping is the default).\
* Type specific destination transforms (typically such as trim or lowercase all strings).  Can be used on any destination type.
* Custom destination creation (not just default constructor)
* Automatic Enum <=> String mapping
* Mapper instance creation for injection situations
* Lots more stuff below...

###Examples
####Mapping to a new object
Fpr makes the object and maps values to it.

    TDestination destObject = TypeAdapter.Adapt<TSource, TDestination>(sourceObject);

####Mapping to an existing object
You make the object, Fpr maps to the object.

    TDestination destObject = new TDestination();
    destObject = TypeAdapter.Adapt(sourceObject, destObject);

####Mapping Lists Included
This includes lists, arrays, collections, enumerables etc...

    var destObjectList = TypeAdapter.Adapt<List<TSource>, List<TDestination>>(sourceList);

####Mapping Enums Included
Fpr maps enums to numerics automatically, but it also maps strings to and from enums automatically in a fast manner.  
The default Enum.ToString() in .Net is quite slow.  The implementation in Fpr is double the speed.  
Likewise, a fast conversion from strings to enums is also included.  If the string is null or empty, 
the enum will initialize to the first enum value.

In addition, fast Enum mapper extension methods are included for convenience.

    //Convert enum to string
    var myEnum = new SomeEnum.FirstValue;
    myEnum.ToFastString();

    //Convert string to enum
    var myEnumString = "FirstValue";
    myEnumString.ToFastEnum<SomeEnum>();
    

####Customized Mapping
When the default convention mappings aren't enough to do the job, you can specify complex source mappings.

    TypeAdapterConfig<TSource, TDestination>()
    .NewConfig()
    .IgnoreMember(dest => dest.Property)
    .MapFrom(dest => dest.FullName, 
             src => string.Format("{0} {1}", src.FirstName, src.LastName));

####Custom Destination Object Creation
You can provide a function call to create your destination objects instead of using the default object creation 
(which expects an empty constructor).  To do so, use the "ConstructUsing()" method when configuring.  This method expects
a function that will provide the destination instance. You can call your own constructor, a factory method, 
or anything else that provides an object of the expected type.

    //Example using a non-default constructor
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
                .ConstructUsing(() => new TDestination("constructorValue"));

    //Example using an object initializer
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
                .ConstructUsing(() => new TDestination{Unmapped = "unmapped"});

####Type-Specific Destination Transforms
This allows transforms for all items of a type, such as trimming all strings.  But really any operation 
can be performed on the destination value before assignment.  This can be set up at either a global
or a mapping level.

    //Global
    TypeAdapterConfig.GlobalSettings.DestinationTransforms.Upsert<string>(x => x.Trim());

    //Per mapping configuration
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
        .DestinationTransforms.Upsert<string>(x => x.Trim());
    

####Conditional Mapping
The MapFrom configuration can accept a third parameter that provides a condition based on the source.
If the condition is not met, the mapping is skipped altogether.

    TypeAdapterConfig<TSource, TDestination>()
        .NewConfig()
        .IgnoreMember(dest => dest.Property)
        .MapFrom(dest => dest.FullName, src => src.FullName, srcCond => srcCond.City == "Victoria");

####Max Depth
When mapping nested or tree-type structures, it's often necessary to specify a max nesting depth to prevent overflows.

    TypeAdapterConfig<TSource, TDestination>
                .NewConfig()
                .MaxDepth(3);

####Queryable Extensions

    using(MyDbContext context = new MyDbContext())
    {
        // Build a Select Expression from DTO
        var destinations = context.Sources.Project().To<Destination>().ToList();

        // Versus creating by hand:
        var destinations = context.Sources.Select(c => new Destination(){
            Id = p.Id,
            Name = p.Name,
            Surname = p.Surname,
            ....
        })
        .ToList();
    }

####Forcing Explicit Mapping
In order to help with "Fail Fast" situations, the following strict mapping modes have been added.
An ArgumentOutOfRange exception will currently be thrown in the situations below if an appropriate mapping and/or source cannot be located.

Forcing all destination properties to have a corresponding source member or explicit mapping/ignore:

    //Default is "false"
    TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource = true;

Forcing all classes to be explicitly mapped:

    //Default is "false"
    TypeAdapterConfig.GlobalSettings.RequireExplicitMapping = true;
    //This means you have to have an explicit configuration for each class, even if it's just:
    TypeAdapterConfig<Source, Destination>.NewConfig();

####Validating Mappings
Both a specific TypeAdapterConfig<Source, Destination> or all current configurations can be validated.  This will throw
and ArgumentOutOfRangeException that contains all of the existing missing destination mappings.  In addition, if Explicit Mappings (above)
are enabled, it will also include errors for classes that are not registered at all with the container.

    //Validate a specific config
    var config = TypeAdapterConfig<Source, Destination>.NewConfig();
    config.Validate();<commit_msg>readme update<commit_after>##Fpr - The Mapper of Your Domain

A fast, fun and stimulating object to object mapper for .Net 4.5.  

Fpr was originally forked from FastMapper (https://fmapper.codeplex.com/).
Fpr maps properties by convention, including nested complex objects and collections, but also supports
explicit mapping.

This fork fixes some issues and includes some additions to make the mapper more configurable and useful for .Net 4.5:

* Support for IReadOnlyList
* Mapping of members with non-public setters
* Automatic mapping of nullable primitives to non-nullable primitives
* Improved error messages that help you find configuration errors
* Conditional mapping
* Assembly scanning for custom mappers
* Strict modes to err if types or members are not explicity mapped (implicit/forgiving mapping is the default).\
* Type specific destination transforms (typically such as trim or lowercase all strings).  Can be used on any destination type.
* Custom destination creation (not just default constructor)
* Automatic Enum <=> String mapping
* Mapper instance creation for injection situations
* Lots more stuff below...

###Examples
####Mapping to a new object
Fpr makes the object and maps values to it.

    TDestination destObject = TypeAdapter.Adapt<TSource, TDestination>(sourceObject);

####Mapping to an existing object
You make the object, Fpr maps to the object.

    TDestination destObject = new TDestination();
    destObject = TypeAdapter.Adapt(sourceObject, destObject);

####Mapping Lists Included
This includes lists, arrays, collections, enumerables etc...

    var destObjectList = TypeAdapter.Adapt<List<TSource>, List<TDestination>>(sourceList);

####Mapping Enums Included
Fpr maps enums to numerics automatically, but it also maps strings to and from enums automatically in a fast manner.  
The default Enum.ToString() in .Net is quite slow.  The implementation in Fpr is double the speed.  
Likewise, a fast conversion from strings to enums is also included.  If the string is null or empty, 
the enum will initialize to the first enum value.

In addition, fast Enum mapper extension methods are included for convenience.

    //Convert enum to string
    var myEnum = new SomeEnum.FirstValue;
    myEnum.ToFastString();

    //Convert string to enum
    var myEnumString = "FirstValue";
    myEnumString.ToFastEnum<SomeEnum>();
    

####Customized Mapping
When the default convention mappings aren't enough to do the job, you can specify complex source mappings.

    TypeAdapterConfig<TSource, TDestination>()
    .NewConfig()
    .IgnoreMember(dest => dest.Property)
    .MapFrom(dest => dest.FullName, 
             src => string.Format("{0} {1}", src.FirstName, src.LastName));

####Custom Destination Object Creation
You can provide a function call to create your destination objects instead of using the default object creation 
(which expects an empty constructor).  To do so, use the "ConstructUsing()" method when configuring.  This method expects
a function that will provide the destination instance. You can call your own constructor, a factory method, 
or anything else that provides an object of the expected type.

    //Example using a non-default constructor
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
                .ConstructUsing(() => new TDestination("constructorValue"));

    //Example using an object initializer
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
                .ConstructUsing(() => new TDestination{Unmapped = "unmapped"});

####Type-Specific Destination Transforms
This allows transforms for all items of a type, such as trimming all strings.  But really any operation 
can be performed on the destination value before assignment.  This can be set up at either a global
or a mapping level.

    //Global
    TypeAdapterConfig.GlobalSettings.DestinationTransforms.Upsert<string>(x => x.Trim());

    //Per mapping configuration
    TypeAdapterConfig<TSource, TDestination>.NewConfig()
        .DestinationTransforms.Upsert<string>(x => x.Trim());
    

####Conditional Mapping
The MapFrom configuration can accept a third parameter that provides a condition based on the source.
If the condition is not met, the mapping is skipped altogether.

    TypeAdapterConfig<TSource, TDestination>()
        .NewConfig()
        .IgnoreMember(dest => dest.Property)
        .MapFrom(dest => dest.FullName, src => src.FullName, srcCond => srcCond.City == "Victoria");

####Max Depth
When mapping nested or tree-type structures, it's often necessary to specify a max nesting depth to prevent overflows.

    TypeAdapterConfig<TSource, TDestination>
                .NewConfig()
                .MaxDepth(3);

####Queryable Extensions

    using(MyDbContext context = new MyDbContext())
    {
        // Build a Select Expression from DTO
        var destinations = context.Sources.Project().To<Destination>().ToList();

        // Versus creating by hand:
        var destinations = context.Sources.Select(c => new Destination(){
            Id = p.Id,
            Name = p.Name,
            Surname = p.Surname,
            ....
        })
        .ToList();
    }

####Forcing Explicit Mapping
In order to help with "Fail Fast" situations, the following strict mapping modes have been added.
An ArgumentOutOfRange exception will currently be thrown in the situations below if an appropriate mapping and/or source cannot be located.

Forcing all destination properties to have a corresponding source member or explicit mapping/ignore:

    //Default is "false"
    TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource = true;

Forcing all classes to be explicitly mapped:

    //Default is "false"
    TypeAdapterConfig.GlobalSettings.RequireExplicitMapping = true;
    //This means you have to have an explicit configuration for each class, even if it's just:
    TypeAdapterConfig<Source, Destination>.NewConfig();

####Validating Mappings
Both a specific TypeAdapterConfig<Source, Destination> or all current configurations can be validated.  This will throw
and ArgumentOutOfRangeException that contains all of the existing missing destination mappings.  In addition, if Explicit Mappings (above)
are enabled, it will also include errors for classes that are not registered at all with the mapper.

    //Validate a specific config
    var config = TypeAdapterConfig<Source, Destination>.NewConfig();
    config.Validate();
{'fraction_non_alphanumeric': 0.07475328308337867, 'fraction_numerical': 0.0010878856165980264, 'mean_word_length': 3.889817629179331, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 63, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1103663', 'n_tokens_mistral': 3214, 'n_tokens_neox': 3137, 'n_words': 1432}