diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..fd4c96d8f9
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+; Top-most http://editorconfig.org/ file
+root = true
+
+[*]
+end_of_line = LF
+indent_style = space
+indent_size = 4
+
+[*.xml]
+indent_size = 2
+
+[*.csproj]
+indent_size = 2
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 84fd327ca5..0944268a01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
build/
release/
scripts/
+artifacts/
.dotnet
TestResults/
*.suo
@@ -26,4 +27,7 @@ project.lock.json
# JetBrains Rider
.idea/
-*.sln.iml
\ No newline at end of file
+*.sln.iml
+
+# Read the Docs
+docs/_build
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000000..af59f269aa
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1 @@
+requirements_file: docs/requirements.txt
diff --git a/AutoMapper.nuspec b/AutoMapper.nuspec
deleted file mode 100644
index 8a57accd54..0000000000
--- a/AutoMapper.nuspec
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
- AutoMapper
- 4.1.1
- Jimmy Bogard
- Jimmy Bogard
- https://github.com/AutoMapper/AutoMapper/blob/master/LICENSE.txt
- http://automapper.org
- https://s3.amazonaws.com/automapper/icon.png
- false
- A convention-based object-object mapper
- A convention-based object-object mapper. AutoMapper uses a fluent configuration API to define an object-object mapping strategy. AutoMapper uses a convention-based matching algorithm to match up source to destination values. Currently, AutoMapper is geared towards model projection scenarios to flatten complex object models to DTOs and other simple objects, whose design is better suited for serialization, communication, messaging, or simply an anti-corruption layer between the domain and application layer.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/AutoMapper.sln b/AutoMapper.sln
new file mode 100644
index 0000000000..8050190642
--- /dev/null
+++ b/AutoMapper.sln
@@ -0,0 +1,100 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.10
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0691ABF2-B3C7-43BF-9862-2D8D1299CE58}"
+ ProjectSection(SolutionItems) = preProject
+ appveyor.yml = appveyor.yml
+ CONTRIBUTING.md = CONTRIBUTING.md
+ default.ps1 = default.ps1
+ Directory.Build.props = Directory.Build.props
+ ISSUE_TEMPLATE.md = ISSUE_TEMPLATE.md
+ README.md = README.md
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmark", "src\Benchmark\Benchmark.csproj", "{B8051389-CB47-46FB-B234-9D49506704AA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper", "src\AutoMapper\AutoMapper.csproj", "{35888286-1428-4BF3-BB0C-D8BC092D0A5D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.UnitTests", "src\UnitTests\AutoMapper.UnitTests.csproj", "{4F96C184-FF4B-4256-B8BC-C51D1167C489}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.IntegrationTests", "src\IntegrationTests\AutoMapper.IntegrationTests.csproj", "{24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Release|ARM.ActiveCfg = Release|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Release|x64.ActiveCfg = Release|Any CPU
+ {B8051389-CB47-46FB-B234-9D49506704AA}.Release|x86.ActiveCfg = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|ARM.Build.0 = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|x64.Build.0 = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Debug|x86.Build.0 = Debug|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|ARM.ActiveCfg = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|ARM.Build.0 = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|x64.ActiveCfg = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|x64.Build.0 = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|x86.ActiveCfg = Release|Any CPU
+ {35888286-1428-4BF3-BB0C-D8BC092D0A5D}.Release|x86.Build.0 = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|x64.Build.0 = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Debug|x86.Build.0 = Debug|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|ARM.Build.0 = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|x64.ActiveCfg = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|x64.Build.0 = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|x86.ActiveCfg = Release|Any CPU
+ {4F96C184-FF4B-4256-B8BC-C51D1167C489}.Release|x86.Build.0 = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|ARM.Build.0 = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|x64.Build.0 = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Debug|x86.Build.0 = Debug|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|ARM.ActiveCfg = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|ARM.Build.0 = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|x64.ActiveCfg = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|x64.Build.0 = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|x86.ActiveCfg = Release|Any CPU
+ {24B47F4C-0035-4F29-AAD9-4C47E1AAD98E}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4D8272EE-D8E3-4B7E-A063-B334CBF8C42F}
+ EndGlobalSection
+EndGlobal
diff --git a/src/AutoMapper.snk b/AutoMapper.snk
similarity index 100%
rename from src/AutoMapper.snk
rename to AutoMapper.snk
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..6264fec06a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,72 @@
+# How to contribute
+
+The easiest way to contribute is to open an issue and start a discussion.
+Then we can decide if and how a feature or a change could be implemented and if you should submit a pull requests with code changes.
+
+Also read this first: [Being a good open source citizen](https://hackernoon.com/being-a-good-open-source-citizen-9060d0ab9732#.x3hocgw85)
+
+## General feedback and discussions
+Please start a discussion on the [core repo issue tracker](https://github.com/AutoMapper/AutoMapper/issues).
+
+## Platform
+AutoMapper is built using the RTM tooling that ships with Visual Studio 2017. This is the only configuration accepted.
+
+## Building
+
+Run `psake.cmd` from the command line. This builds and runs tests.
+
+## Bugs and feature requests?
+Please log a new issue in the appropriate GitHub repo:
+
+* [Core](https://github.com/AutoMapper/AutoMapper)
+* [EF6 Extensions](https://github.com/AutoMapper/AutoMapper.EF6)
+* [IDataReader/Record Extensions](https://github.com/AutoMapper/AutoMapper.Data)
+* [Collection Extensions](https://github.com/AutoMapper/AutoMapper.Collection)
+* [Microsoft DI Extensions](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection)
+
+## Other discussions
+https://gitter.im/AutoMapper/AutoMapper
+
+## Filing issues
+The best way to get your bug fixed is to be as detailed as you can be about the problem.
+Providing a minimal project with steps to reproduce the problem is ideal.
+Here are questions you can answer before you file a bug to make sure you're not missing any important information.
+
+1. Did you read the [documentation](https://automapper.readthedocs.io/en/latest/)?
+2. Did you include the snippet of broken code in the issue?
+3. What are the *EXACT* steps to reproduce this problem (including source/destination types, mapping configuration and execution)?
+
+GitHub supports [markdown](https://github.github.com/github-flavored-markdown/), so when filing bugs make sure you check the formatting before clicking submit.
+
+## Contributing code and content
+You will need to sign a [Contributor License Agreement](https://cla.dotnetfoundation.org/) before submitting your pull request.
+
+Make sure you can build the code. Familiarize yourself with the project workflow and our coding conventions. If you don't know what a pull request is read this article: https://help.github.com/articles/using-pull-requests.
+
+**We only accept PRs to the master branch.**
+
+Before submitting a feature or substantial code contribution please discuss it with the team and ensure it follows the product roadmap. Here's a list of blog posts that are worth reading before doing a pull request:
+
+* [Open Source Contribution Etiquette](http://tirania.org/blog/archive/2010/Dec-31.html) by Miguel de Icaza
+* [Don't "Push" Your Pull Requests](http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/) by Ilya Grigorik.
+* [10 tips for better Pull Requests](http://blog.ploeh.dk/2015/01/15/10-tips-for-better-pull-requests/) by Mark Seemann
+* [How to write the perfect pull request](https://github.com/blog/1943-how-to-write-the-perfect-pull-request) by GitHub
+
+Here's a few things you should always do when making changes to the code base:
+
+**Commit/Pull Request Format**
+
+```
+Summary of the changes (Less than 80 chars)
+ - Detail 1
+ - Detail 2
+
+#bugnumber (in this specific format)
+```
+
+**Tests**
+
+- Tests need to be provided for every bug/feature that is completed.
+- Tests only need to be present for issues that need to be verified by QA (e.g. not tasks).
+- If there is a scenario that is far too hard to test there does not need to be a test for it.
+ - "Too hard" is determined by the team as a whole.
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000000..ca71a5fe41
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,12 @@
+
+
+
+ 8.1.0
+ Jimmy Bogard
+ latest
+ true
+ $(NoWarn);1701;1702;1591
+ true
+
+
+
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..f9ff3d2df7
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,38 @@
+
+
+
+### Source/destination types
+
+```csharp
+// Put your source/destination types here
+```
+
+### Mapping configuration
+
+```csharp
+// Mapper.Initialize or just the CreateMap snippet
+```
+
+### Version: x.y.z
+
+
+### Expected behavior
+
+
+
+### Actual behavior
+
+
+
+### Steps to reproduce
+
+```csharp
+// Your calls to Mapper.Map or ProjectTo here, with source/destination objects constructed
+```
diff --git a/LICENSE.txt b/LICENSE.txt
index 0e750de961..ed254c2438 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,7 +1,9 @@
+The MIT License (MIT)
+
Copyright (c) 2010 Jimmy Bogard
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index acc7c2da8a..162265b182 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,63 @@
-
-================================
+
-[](https://ci.appveyor.com/project/jbogard/automapper/branch/develop)
-[](https://www.nuget.org/packages/AutoMapper/)
+[](https://ci.appveyor.com/project/jbogard/automapper/branch/master)
[](https://www.nuget.org/packages/AutoMapper/)
-[](http://myget.org/gallery/automapperdev)
+[](http://myget.org/gallery/automapperdev)
+
+### What is AutoMapper?
-What is AutoMapper?
---------------------------------
AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another. This type of code is rather dreary and boring to write, so why not invent a tool to do it for us?
-How do I get started?
---------------------------------
-Check out the [getting started guide](https://github.com/AutoMapper/AutoMapper/wiki/Getting-started). When you're done there, the [wiki](https://github.com/AutoMapper/AutoMapper/wiki) goes in to the nitty-gritty details. Finally, check out the [dnrTV episode](http://www.dnrtv.com/default.aspx?showNum=155) for a full walkthrough. If you have questions, you can post them to the [Mailing List](http://groups.google.com/group/automapper-users).
+This is the main repository for AutoMapper, but there's more:
+
+* [EF6 Extensions](https://github.com/AutoMapper/AutoMapper.EF6)
+* [IDataReader/Record Extensions](https://github.com/AutoMapper/AutoMapper.Data)
+* [Collection Extensions](https://github.com/AutoMapper/AutoMapper.Collection)
+* [Microsoft DI Extensions](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection)
+* [Expression Mapping](https://github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping)
+
+### How do I get started?
+
+First, configure AutoMapper to know what types you want to map, in the startup of your application:
+
+```csharp
+Mapper.Initialize(cfg => {
+ cfg.CreateMap();
+ cfg.CreateMap();
+});
+```
+Then in your application code, execute the mappings:
+
+```csharp
+var fooDto = Mapper.Map(foo);
+var barDto = Mapper.Map(bar);
+```
+
+Check out the [getting started guide](https://automapper.readthedocs.io/en/latest/Getting-started.html). When you're done there, the [wiki](https://automapper.readthedocs.io/en/latest/) goes in to the nitty-gritty details. If you have questions, you can post them to [Stack Overflow](https://stackoverflow.com/questions/tagged/automapper) or in our [Gitter](https://gitter.im/AutoMapper/AutoMapper).
+
+### Where can I get it?
-Where can I get it?
---------------------------------
First, [install NuGet](http://docs.nuget.org/docs/start-here/installing-nuget). Then, install [AutoMapper](https://www.nuget.org/packages/AutoMapper/) from the package manager console:
- PM> Install-Package AutoMapper
+```
+PM> Install-Package AutoMapper
+```
+
+### Do you have an issue?
+
+First check if it's already fixed by trying the [MyGet build](https://automapper.readthedocs.io/en/latest/The-MyGet-build.html).
+
+You might want to know exactly what [your mapping does](https://automapper.readthedocs.io/en/latest/Understanding-your-mapping.html) at runtime.
+
+If you're still running into problems, file an issue above.
+
+### License, etc.
+
+This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
+For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
+
+AutoMapper is Copyright © 2009 [Jimmy Bogard](https://jimmybogard.com) and other contributors under the [MIT license](LICENSE.txt).
+
+### .NET Foundation
-AutoMapper is Copyright © 2008-2012 [Jimmy Bogard](http://jimmybogard.lostechies.com) and other contributors under the [MIT license](LICENSE.txt).
+This project is supported by the [.NET Foundation](https://dotnetfoundation.org).
diff --git a/RefGen.exe b/RefGen.exe
deleted file mode 100644
index d1721c246e..0000000000
Binary files a/RefGen.exe and /dev/null differ
diff --git a/appveyor.yml b/appveyor.yml
index 08a47295ca..257f2fa2a1 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,11 +4,11 @@ pull_requests:
branches:
only:
- master
-services: mssql2014
+image: Visual Studio 2017
nuget:
disable_publish_on_pr: true
build_script:
-- cmd: .\psake.bat ci
+- cmd: .\psake.cmd ci
test: off
artifacts:
- path: src\AutoMapper\bin\release\*.nupkg
@@ -27,4 +27,4 @@ deploy:
secure: t3blEIQiDIYjjWhOSTTtrcAnzJkmSi+0zYPxC1v4RDzm6oI/gIpD6ZtrOGsYu2jE
on:
branch: master
- appveyor_repo_tag: true
\ No newline at end of file
+ appveyor_repo_tag: true
diff --git a/default.ps1 b/default.ps1
index ca1a5200f2..bb53962b04 100644
--- a/default.ps1
+++ b/default.ps1
@@ -1,94 +1,64 @@
-Framework '4.5.1x86'
-
properties {
$base_dir = resolve-path .
$build_dir = "$base_dir\build"
$source_dir = "$base_dir\src"
$result_dir = "$build_dir\results"
$global:config = "debug"
+ $tag = $(git tag -l --points-at HEAD)
+ $revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL];
+ $suffix = @{ $true = ""; $false = "ci-$revision"}[$tag -ne $NULL -and $revision -ne "local"]
+ $commitHash = $(git rev-parse --short HEAD)
+ $buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""]
+ $versionSuffix = @{ $true = "--version-suffix=$($suffix)"; $false = ""}[$suffix -ne ""]
}
task default -depends local
-task local -depends init, compile, test
-task ci -depends clean, release, local, benchmark
+task local -depends compile, test
+task ci -depends clean, release, local, pack, benchmark
task clean {
rd "$source_dir\artifacts" -recurse -force -ErrorAction SilentlyContinue | out-null
rd "$base_dir\build" -recurse -force -ErrorAction SilentlyContinue | out-null
}
-task init {
- # Make sure per-user dotnet is installed
- Install-Dotnet
-}
-
task release {
$global:config = "release"
}
task compile -depends clean {
- $version = if ($env:APPVEYOR_BUILD_NUMBER -ne $NULL) { $env:APPVEYOR_BUILD_NUMBER } else { '0' }
- $version = "{0:D5}" -f [convert]::ToInt32($version, 10)
+ echo "build: Tag is $tag"
+ echo "build: Package version suffix is $suffix"
+ echo "build: Build version suffix is $buildSuffix"
- exec { & $source_dir\.nuget\Nuget.exe restore $source_dir\AutoMapper.sln }
+ exec { dotnet --version }
+ exec { dotnet --info }
- exec { msbuild /t:Clean /t:Build /p:Configuration=$config /v:q /p:NoWarn=1591 /nologo $source_dir\AutoMapper.sln }
+ exec { dotnet build -c $config --version-suffix=$buildSuffix }
+}
- exec { dotnet pack $source_dir\AutoMapper -c $config --version-suffix $version}
+task pack -depends compile {
+ exec { dotnet pack $source_dir\AutoMapper\AutoMapper.csproj -c $config --no-build $versionSuffix }
}
task benchmark {
- exec { & $source_dir\Benchmark\bin\$config\Benchmark.exe }
+ exec { & $source_dir\Benchmark\bin\$config\net461\Benchmark.exe }
}
task test {
- $testRunners = @(gci $source_dir\packages -rec -filter Fixie.Console.exe)
+ Push-Location -Path $source_dir\UnitTests
- if ($testRunners.Length -ne 1)
- {
- throw "Expected to find 1 Fixie.Console.exe, but found $($testRunners.Length)."
+ try {
+ exec { & dotnet test -c $config --no-build --no-restore }
+ } finally {
+ Pop-Location
}
- $testRunner = $testRunners[0].FullName
-
- exec { & $testRunner $source_dir/UnitTests/bin/$config/AutoMapper.UnitTests.Net4.dll }
- exec { & $testRunner $source_dir/UnitTests.Portable/bin/$config/AutoMapper.UnitTests.Portable.dll }
- exec { & $testRunner $source_dir/IntegrationTests.Net4/bin/$config/AutoMapper.IntegrationTests.Net4.dll }
-}
-
-function Install-Dotnet
-{
- $dotnetcli = where-is('dotnet')
-
- if($dotnetcli -eq $null)
- {
- $dotnetPath = "$pwd\.dotnet"
- $dotnetCliVersion = if ($env:DOTNET_CLI_VERSION -eq $null) { 'Latest' } else { $env:DOTNET_CLI_VERSION }
- $dotnetInstallScriptUrl = 'https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/install.ps1'
- $dotnetInstallScriptPath = '.\scripts\obtain\install.ps1'
+ Push-Location -Path $source_dir\IntegrationTests
- md -Force ".\scripts\obtain\" | Out-Null
- curl $dotnetInstallScriptUrl -OutFile $dotnetInstallScriptPath
- & .\scripts\obtain\install.ps1 -Channel "preview" -version $dotnetCliVersion -InstallDir $dotnetPath -NoPath
- $env:Path = "$dotnetPath;$env:Path"
- }
+ try {
+ exec { & dotnet test -c $config --no-build --no-restore }
+ } finally {
+ Pop-Location
+ }
}
-
-function where-is($command) {
- (ls env:\path).Value.split(';') | `
- where { $_ } | `
- %{ [System.Environment]::ExpandEnvironmentVariables($_) } | `
- where { test-path $_ } |`
- %{ ls "$_\*" -include *.bat,*.exe,*cmd } | `
- %{ $file = $_.Name; `
- if($file -and ($file -eq $command -or `
- $file -eq ($command + '.exe') -or `
- $file -eq ($command + '.bat') -or `
- $file -eq ($command + '.cmd'))) `
- { `
- $_.FullName `
- } `
- } | `
- select -unique
-}
\ No newline at end of file
diff --git a/docs/5.0-Upgrade-Guide.md b/docs/5.0-Upgrade-Guide.md
new file mode 100644
index 0000000000..ad63fe41b6
--- /dev/null
+++ b/docs/5.0-Upgrade-Guide.md
@@ -0,0 +1,96 @@
+# 5.0 Upgrade Guide
+
+## Initialization
+
+You now must use either `Mapper.Initialize` or `new MapperConfiguration()` to initialize AutoMapper. If you prefer to keep the static usage, use `Mapper.Initialize`.
+
+If you have a lot of `Mapper.CreateMap` calls everywhere, move those to a Profile, or into `Mapper.Initialize`, called once at startup.
+
+For examples see [here](Static-and-Instance-API.html).
+
+## Profiles
+
+Instead of overriding a Configure method, you configure directly via the constructor:
+
+```c#
+public class MappingProfile : Profile {
+ public MappingProfile() {
+ CreateMap();
+ RecognizePrefix("m_");
+ }
+}
+```
+
+## IgnoreAllNonExisting extension
+
+A popular Stack Overflow post introduced the idea of ignoring all non-existing members on the destination type. It used things that don't exist anymore in the configuration API. This functionality is really only intended for configuration validation.
+
+In 5.0, you can use ReverseMap or CreateMap passing in the MemberList enum to validate against the source members (or no members). Any place you have this IgnoreAllNonExisting extension, use the CreateMap overload that validates against the source or no members:
+
+```c#
+cfg.CreateMap(MemberList.None);
+```
+
+## Resolution Context things
+
+ResolutionContext used to capture a lot of information, source and destination values, along with a hierarchical parent model. For source/destination values, all of the interfaces (value resolvers and type converters) along with config options now include the source/destination values, and if applicable, source/destination members.
+
+If you're trying to access some parent object in your model, you will need to add those relationships to your models and access them through those relationships, and not through AutoMapper's hierarchy. The ResolutionContext was pared down for both performance and sanity reasons.
+
+## Value resolvers
+
+The signature of a value resolver has changed to allow access to the source/destination models. Additionally, the base class is gone in favor of interfaces. For value resolvers that do not have a member redirection, the interface is now:
+
+```c#
+public interface IValueResolver
+{
+ TDestMember Resolve(TSource source, TDestination destination, TDestMember destMember, ResolutionContext context);
+}
+```
+
+You have access now to the source model, destination model, and destination member this resolver is configured against.
+
+If you are using a ResolveUsing and passing in the `FromMember` configuration, this is now a new resolver interface:
+
+```c#
+public interface IMemberValueResolver
+{
+ TDestMember Resolve(TSource source, TDestination destination, TSourceMember sourceMember, TDestMember destMember, ResolutionContext context);
+}
+```
+
+This is now configured directly as `ForMember(dest => dest.Foo, opt => opt.ResolveUsing(src => src.Bar)`
+
+## Type converters
+
+The base class for a type converter is now gone in favor of a single interface that accepts the source and destination objects and returns the destination object:
+
+```c#
+public interface ITypeConverter
+{
+ TDestination Convert(TSource source, TDestination destination, ResolutionContext context);
+}
+```
+
+## Circular references
+
+Previously, AutoMapper could handle circular references by keeping track of what was mapped, and on every mapping, check a local hashtable of source/destination objects to see if the item was already mapped. It turns out this tracking is very expensive, and you need to opt-in using PreserveReferences for circular maps to work. Alternatively, you can configure MaxDepth:
+
+```c#
+// Self-referential mapping
+cfg.CreateMap().MaxDepth(3);
+
+// Circular references between users and groups
+cfg.CreateMap().PreserveReferences();
+```
+
+Starting from 6.1.0 PreserveReferences is set automatically at config time whenever the recursion can be detected statically. If that doesn't happen in your case, open an issue with a full repro and we'll look into it.
+
+## UseDestinationValue
+
+UseDestinationValue tells AutoMapper not to create a new object for some member, but to use the existing property of the destination object. It used to be true by default. Consider whether this applies to your case. Check [recent issues](https://github.com/AutoMapper/AutoMapper/search?o=desc&q=UseDestinationValue&s=created&type=Issues&utf8=%E2%9C%93).
+
+```c#
+cfg.CreateMap()
+ .ForMember(d => d.Child, opt => opt.UseDestinationValue());
+```
diff --git a/docs/8.0-Upgrade-Guide.md b/docs/8.0-Upgrade-Guide.md
new file mode 100644
index 0000000000..7447d706a5
--- /dev/null
+++ b/docs/8.0-Upgrade-Guide.md
@@ -0,0 +1,172 @@
+# 8.0 Upgrade Guide
+
+## ProjectUsing
+
+The `ProjectUsing` method consolidated with `ConvertUsing`:
+
+```c#
+// IMappingExpression
+
+// Old
+void ConvertUsing(Func mappingFunction);
+void ProjectUsing(Expression> mappingExpression);
+
+// New
+void ConvertUsing(Expression> mappingExpression);
+```
+
+To migrate, replace all usages of `ProjectUsing` with `ConvertUsing`.
+
+The `ConvertUsing` expression-based method will be used for both in-memory mapping and LINQ projections. You cannot have separate configuration for in-memory vs. LINQ projections.
+
+### Existing `ConvertUsing` usages
+
+The change from `Func` to `Expression` may break some existing usages. Namely:
+
+- `ConvertUsing` using lambda statements, method groups, or delegates
+- Dual configuration of `ProjectUsing` and `ConvertUsing`
+
+For the first case, you may either:
+
+- Convert to a lambda expression
+- Move to the `Func`-based overloads
+
+The `Func`-based overloads accept more parameters, so you may have to add the parameters to your delegates.
+
+### Motivation
+
+Simplify overloads, and to make it clear that you cannot have separate configuration for LINQ projections vs. in-memory mapping.
+
+## ConstructProjectionUsing
+
+The `ConstructProjectionUsing` method consolidated with `ConstructUsing`:
+
+```c#
+// IMappingExpression
+
+// Old
+IMappingExpression ConstructUsing(Func ctor);
+IMappingExpression ConstructUsing(Func ctor);
+IMappingExpression ConstructProjectionUsing(Expression> ctorExpression);
+
+// New
+IMappingExpression ConstructUsing(Expression> ctor);
+IMappingExpression ConstructUsing(Func ctor);
+
+// IMappingExpression
+
+// Old
+IMappingExpression ConstructUsing(Func