diff --git a/AgileMapper.PerformanceTester.Net45/AgileMapper.PerformanceTester.Net45.csproj b/AgileMapper.PerformanceTester.Net45/AgileMapper.PerformanceTester.Net45.csproj
index 6d774bf3e..dc1e079ff 100644
--- a/AgileMapper.PerformanceTester.Net45/AgileMapper.PerformanceTester.Net45.csproj
+++ b/AgileMapper.PerformanceTester.Net45/AgileMapper.PerformanceTester.Net45.csproj
@@ -37,8 +37,8 @@
..\packages\AgileObjects.NetStandardPolyfills.1.4.0\lib\net40\AgileObjects.NetStandardPolyfills.dll
-
- ..\packages\AgileObjects.ReadableExpressions.2.1.1\lib\net40\AgileObjects.ReadableExpressions.dll
+
+ ..\packages\AgileObjects.ReadableExpressions.2.3.2\lib\net40\AgileObjects.ReadableExpressions.dll
..\packages\AutoMapper.7.0.1\lib\net45\AutoMapper.dll
diff --git a/AgileMapper.PerformanceTester.Net45/packages.config b/AgileMapper.PerformanceTester.Net45/packages.config
index fcd3dee54..24b54cac7 100644
--- a/AgileMapper.PerformanceTester.Net45/packages.config
+++ b/AgileMapper.PerformanceTester.Net45/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/AgileMapper.UnitTests.Common/ShouldExtensions.cs b/AgileMapper.UnitTests.Common/ShouldExtensions.cs
index 4fd39e6de..9eb41e0c4 100644
--- a/AgileMapper.UnitTests.Common/ShouldExtensions.cs
+++ b/AgileMapper.UnitTests.Common/ShouldExtensions.cs
@@ -52,7 +52,9 @@ public static void ShouldBe(this TActual value, TExpected ex
{
if (!AreEqual(expectedValue, value))
{
- Asplode(expectedValue.ToString(), value?.ToString());
+ Asplode(
+ expectedValue?.ToString() ?? (typeof(TExpected).CanBeNull() ? "null" : "default"),
+ value?.ToString() ?? (typeof(TActual).CanBeNull() ? "null" : "default"));
}
}
@@ -405,14 +407,18 @@ public static IDictionary ShouldContainKeyAndValue(
return dictionary;
}
- public static void ShouldBeOfType(this object actual)
+ public static TExpected ShouldBeOfType(this object actual)
{
- if (!(actual is TExpected))
+ if (actual is TExpected expected)
{
- Asplode(
- "An object of type " + typeof(TExpected).GetFriendlyName(),
- actual.GetType().GetFriendlyName());
+ return expected;
}
+
+ Asplode(
+ "An object of type " + typeof(TExpected).GetFriendlyName(),
+ actual.GetType().GetFriendlyName());
+
+ return default(TExpected);
}
public static void ShouldContain(this IList actual, T expected)
diff --git a/AgileMapper.UnitTests.Net35/AgileMapper.UnitTests.Net35.csproj b/AgileMapper.UnitTests.Net35/AgileMapper.UnitTests.Net35.csproj
index 7f64f66af..fec9a2f6d 100644
--- a/AgileMapper.UnitTests.Net35/AgileMapper.UnitTests.Net35.csproj
+++ b/AgileMapper.UnitTests.Net35/AgileMapper.UnitTests.Net35.csproj
@@ -37,8 +37,8 @@
..\packages\AgileObjects.NetStandardPolyfills.1.4.0\lib\net35\AgileObjects.NetStandardPolyfills.dll
-
- ..\packages\AgileObjects.ReadableExpressions.2.1.1\lib\net35\AgileObjects.ReadableExpressions.dll
+
+ ..\packages\AgileObjects.ReadableExpressions.2.3.2\lib\net35\AgileObjects.ReadableExpressions.dll
..\packages\DynamicLanguageRuntime.1.1.2\lib\Net35\Microsoft.Dynamic.dll
@@ -66,8 +66,599 @@
-
- %(RecursiveDir)%(Filename)%(Extension)
+
+ Caching\WhenCachingWithHashCodes.cs
+
+
+ Configuration\AssemblyScanningTestClassBase.cs
+
+
+ Configuration\Inline\InlineMappingExtensions.cs
+
+
+ Configuration\Inline\WhenConfiguringCallbacksInline.cs
+
+
+ Configuration\Inline\WhenConfiguringConstructorDataSourcesInline.cs
+
+
+ Configuration\Inline\WhenConfiguringDataSourcesInline.cs
+
+
+ Configuration\Inline\WhenConfiguringDataSourcesInlineIncorrectly.cs
+
+
+ Configuration\Inline\WhenConfiguringDerivedTypesInline.cs
+
+
+ Configuration\Inline\WhenConfiguringEntityMappingInline.cs
+
+
+ Configuration\Inline\WhenConfiguringEnumMappingInline.cs
+
+
+ Configuration\Inline\WhenConfiguringNameMatchingInline.cs
+
+
+ Configuration\Inline\WhenConfiguringObjectCreationInline.cs
+
+
+ Configuration\Inline\WhenConfiguringObjectTrackingInline.cs
+
+
+ Configuration\Inline\WhenConfiguringStringFormattingInline.cs
+
+
+ Configuration\Inline\WhenConfiguringTypeIdentifiersInline.cs
+
+
+ Configuration\Inline\WhenIgnoringMembersInline.cs
+
+
+ Configuration\Inline\WhenIgnoringMembersInlineIncorrectly.cs
+
+
+ Configuration\Inline\WhenMappingToNullInline.cs
+
+
+ Configuration\Inline\WhenValidatingMappingsInline.cs
+
+
+ Configuration\Inline\WhenViewingMappingPlans.cs
+
+
+ Configuration\WhenApplyingMapperConfigurations.cs
+
+
+ Configuration\WhenApplyingMapperConfigurationsIncorrectly.cs
+
+
+ Configuration\WhenConfiguringConstructorDataSources.cs
+
+
+ Configuration\WhenConfiguringDataSources.cs
+
+
+ Configuration\WhenConfiguringDataSourcesIncorrectly.cs
+
+
+ Configuration\WhenConfiguringDerivedTypes.cs
+
+
+ Configuration\WhenConfiguringDerivedTypesIncorrectly.cs
+
+
+ Configuration\WhenConfiguringEntityMapping.cs
+
+
+ Configuration\WhenConfiguringEnumMapping.cs
+
+
+ Configuration\WhenConfiguringExceptionHandling.cs
+
+
+ Configuration\WhenConfiguringMappingCallbacks.cs
+
+
+ Configuration\WhenConfiguringNameMatching.cs
+
+
+ Configuration\WhenConfiguringObjectCreation.cs
+
+
+ Configuration\WhenConfiguringObjectCreationCallbacks.cs
+
+
+ Configuration\WhenConfiguringObjectTracking.cs
+
+
+ Configuration\WhenConfiguringObjectTrackingIncorrectly.cs
+
+
+ Configuration\WhenConfiguringReverseDataSources.cs
+
+
+ Configuration\WhenConfiguringReverseDataSourcesIncorrectly.cs
+
+
+ Configuration\WhenConfiguringStringFormatting.cs
+
+
+ Configuration\WhenConfiguringTypeIdentifiers.cs
+
+
+ Configuration\WhenIgnoringMembers.cs
+
+
+ Configuration\WhenIgnoringMembersByFilter.cs
+
+
+ Configuration\WhenIgnoringMembersByGlobalFilter.cs
+
+
+ Configuration\WhenIgnoringMembersIncorrectly.cs
+
+
+ Configuration\WhenMappingToNull.cs
+
+
+ Configuration\WhenResolvingServices.cs
+
+
+ Configuration\WhenViewingMappingPlans.cs
+
+
+ Dictionaries\Configuration\WhenConfiguringDictionaryMappingIncorrectly.cs
+
+
+ Dictionaries\Configuration\WhenConfiguringNestedDictionaryMapping.cs
+
+
+ Dictionaries\Configuration\WhenConfiguringSourceDictionaryMapping.cs
+
+
+ Dictionaries\Configuration\WhenConfiguringTargetDictionaryMapping.cs
+
+
+ Dictionaries\WhenCreatingRootDictionaryMembers.cs
+
+
+ Dictionaries\WhenFlatteningToDictionaries.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesOnToComplexTypes.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesOnToEnumerableMembers.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesOverComplexTypes.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesToNewComplexTypeMembers.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesToNewComplexTypes.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesToNewEnumerableMembers.cs
+
+
+ Dictionaries\WhenMappingFromDictionariesToNewEnumerables.cs
+
+
+ Dictionaries\WhenMappingFromDictionaryMembers.cs
+
+
+ Dictionaries\WhenMappingOnToDictionaries.cs
+
+
+ Dictionaries\WhenMappingOnToDictionaryMembers.cs
+
+
+ Dictionaries\WhenMappingOverDictionaries.cs
+
+
+ Dictionaries\WhenMappingOverDictionaryMembers.cs
+
+
+ Dictionaries\WhenMappingToNewDictionaries.cs
+
+
+ Dictionaries\WhenMappingToNewDictionaryMembers.cs
+
+
+ Dictionaries\WhenUnflatteningFromDictionaries.cs
+
+
+ Dictionaries\WhenViewingDictionaryMappingPlans.cs
+
+
+ Extensions\Internal\WhenEquatingExpressions.cs
+
+
+ Extensions\Internal\WhenGeneratingVariableNames.cs
+
+
+ Extensions\WhenFlatteningToQueryStringViaExtensionMethods.cs
+
+
+ Extensions\WhenFlatteningViaExtensionMethods.cs
+
+
+ Extensions\WhenMappingViaExtensionMethods.cs
+
+
+ Extensions\WhenUnflatteningFromQueryStringsViaExtensionMethods.cs
+
+
+ Extensions\WhenUnflatteningViaExtensionMethods.cs
+
+
+ MapperCloning\WhenCloningConstructorDataSources.cs
+
+
+ MapperCloning\WhenCloningDataSources.cs
+
+
+ MapperCloning\WhenCloningDictionarySettings.cs
+
+
+ MapperCloning\WhenCloningMemberIgnores.cs
+
+
+ MapperCloning\WhenCloningObjectFactories.cs
+
+
+ MapperCloning\WhenCloningStringFormatting.cs
+
+
+ Members\MemberTestsBase.cs
+
+
+ Members\WhenCreatingTargetMembersFromExpressions.cs
+
+
+ Members\WhenDeterminingATypeIdentifier.cs
+
+
+ Members\WhenDeterminingRecursion.cs
+
+
+ Members\WhenFindingDataSources.cs
+
+
+ Members\WhenFindingSourceMembers.cs
+
+
+ Members\WhenFindingTargetMembers.cs
+
+
+ Members\WhenMatchingSourceToTargetMembers.cs
+
+
+ Properties\AssemblyInfo.cs
+
+
+ Reflection\WhenAccessingTypeInformation.cs
+
+
+ SimpleTypeConversion\WhenConvertingToBools.cs
+
+
+ SimpleTypeConversion\WhenConvertingToBytes.cs
+
+
+ SimpleTypeConversion\WhenConvertingToCharacters.cs
+
+
+ SimpleTypeConversion\WhenConvertingToDateTimes.cs
+
+
+ SimpleTypeConversion\WhenConvertingToDecimals.cs
+
+
+ SimpleTypeConversion\WhenConvertingToDoubles.cs
+
+
+ SimpleTypeConversion\WhenConvertingToEnums.cs
+
+
+ SimpleTypeConversion\WhenConvertingToFlagsEnums.cs
+
+
+ SimpleTypeConversion\WhenConvertingToGuids.cs
+
+
+ SimpleTypeConversion\WhenConvertingToInts.cs
+
+
+ SimpleTypeConversion\WhenConvertingToLongs.cs
+
+
+ SimpleTypeConversion\WhenConvertingToShorts.cs
+
+
+ SimpleTypeConversion\WhenConvertingToStrings.cs
+
+
+ Structs\Configuration\WhenConfiguringStructCreationCallbacks.cs
+
+
+ Structs\Configuration\WhenConfiguringStructDataSources.cs
+
+
+ Structs\Configuration\WhenConfiguringStructMappingCallbacks.cs
+
+
+ Structs\Dictionaries\WhenMappingFromDictionariesToStructs.cs
+
+
+ Structs\WhenMappingOnToStructMembers.cs
+
+
+ Structs\WhenMappingOnToStructs.cs
+
+
+ Structs\WhenMappingOverStructMembers.cs
+
+
+ Structs\WhenMappingOverStructs.cs
+
+
+ Structs\WhenMappingToNewStructMembers.cs
+
+
+ Structs\WhenMappingToNewStructs.cs
+
+
+ Structs\WhenMappingToStructEnumerables.cs
+
+
+ Structs\WhenMappingToUnmappableStructMembers.cs
+
+
+ TestClasses\Address.cs
+
+
+ TestClasses\CategoryDto.cs
+
+
+ TestClasses\CategoryEntity.cs
+
+
+ TestClasses\Child.cs
+
+
+ TestClasses\Customer.cs
+
+
+ TestClasses\CustomerViewModel.cs
+
+
+ TestClasses\DtoBase.cs
+
+
+ TestClasses\Earthworm.cs
+
+
+ TestClasses\EntityBase.cs
+
+
+ TestClasses\FacebookUser.cs
+
+
+ TestClasses\InternalField.cs
+
+
+ TestClasses\IPublicInterface.cs
+
+
+ TestClasses\MegaProduct.cs
+
+
+ TestClasses\MysteryCustomer.cs
+
+
+ TestClasses\MysteryCustomerViewModel.cs
+
+
+ TestClasses\Order.cs
+
+
+ TestClasses\OrderDto.cs
+
+
+ TestClasses\OrderEntity.cs
+
+
+ TestClasses\OrderItem.cs
+
+
+ TestClasses\OrderItemDto.cs
+
+
+ TestClasses\OrderItemEntity.cs
+
+
+ TestClasses\OrderUk.cs
+
+
+ TestClasses\OrderUs.cs
+
+
+ TestClasses\Parent.cs
+
+
+ TestClasses\PaymentTypeUk.cs
+
+
+ TestClasses\PaymentTypeUs.cs
+
+
+ TestClasses\Person.cs
+
+
+ TestClasses\PersonViewModel.cs
+
+
+ TestClasses\Product.cs
+
+
+ TestClasses\ProductDto.cs
+
+
+ TestClasses\ProductDtoMega.cs
+
+
+ TestClasses\ProductEntity.cs
+
+
+ TestClasses\PublicCtor.cs
+
+
+ TestClasses\PublicCtorStruct.cs
+
+
+ TestClasses\PublicEnumerable.cs
+
+
+ TestClasses\PublicField.cs
+
+
+ TestClasses\PublicGetMethod.cs
+
+
+ TestClasses\PublicImplementation.cs
+
+
+ TestClasses\PublicIndex.cs
+
+
+ TestClasses\PublicProperty.cs
+
+
+ TestClasses\PublicPropertyStruct.cs
+
+
+ TestClasses\PublicReadOnlyField.cs
+
+
+ TestClasses\PublicReadOnlyProperty.cs
+
+
+ TestClasses\PublicSealed.cs
+
+
+ TestClasses\PublicSetMethod.cs
+
+
+ TestClasses\PublicTwoFields.cs
+
+
+ TestClasses\PublicTwoFieldsStruct.cs
+
+
+ TestClasses\PublicTwoParamCtor.cs
+
+
+ TestClasses\PublicUnconstructable.cs
+
+
+ TestClasses\PublicWriteOnlyProperty.cs
+
+
+ TestClasses\SaveOrderItemRequest.cs
+
+
+ TestClasses\SaveOrderRequest.cs
+
+
+ TestClasses\Status.cs
+
+
+ TestClasses\StringKeyedDictionary.cs
+
+
+ TestClasses\Title.cs
+
+
+ TestClasses\TitleShortlist.cs
+
+
+ TestClasses\Wedding.cs
+
+
+ TestClasses\WeddingDto.cs
+
+
+ WhenAnalysingCollections.cs
+
+
+ WhenMappingCircularReferences.cs
+
+
+ WhenMappingDerivedTypes.cs
+
+
+ WhenMappingEntities.cs
+
+
+ WhenMappingOnToComplexTypeMembers.cs
+
+
+ WhenMappingOnToComplexTypes.cs
+
+
+ WhenMappingOnToEnumerableMembers.cs
+
+
+ WhenMappingOnToEnumerables.cs
+
+
+ WhenMappingOverComplexTypeMembers.cs
+
+
+ WhenMappingOverComplexTypes.cs
+
+
+ WhenMappingOverEnumerableMembers.cs
+
+
+ WhenMappingOverEnumerables.cs
+
+
+ WhenMappingToConstructors.cs
+
+
+ WhenMappingToMetaMembers.cs
+
+
+ WhenMappingToNewComplexTypeMembers.cs
+
+
+ WhenMappingToNewComplexTypes.cs
+
+
+ WhenMappingToNewEnumerableMembers.cs
+
+
+ WhenMappingToNewEnumerables.cs
+
+
+ WhenUnflatteningFromQueryStrings.cs
+
+
+ WhenUsingFactoryMethods.cs
+
+
+ WhenValidatingMappings.cs
+
+
+ WhenViewingMappingPlans.cs
+
+
+ WhenWorkingWithQueryStrings.cs
diff --git a/AgileMapper.UnitTests.Net35/packages.config b/AgileMapper.UnitTests.Net35/packages.config
index 737e3b5da..0f40009f4 100644
--- a/AgileMapper.UnitTests.Net35/packages.config
+++ b/AgileMapper.UnitTests.Net35/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/AgileMapper.UnitTests.NonParallel/AgileMapper.UnitTests.NonParallel.csproj b/AgileMapper.UnitTests.NonParallel/AgileMapper.UnitTests.NonParallel.csproj
index ab86a47df..538211964 100644
--- a/AgileMapper.UnitTests.NonParallel/AgileMapper.UnitTests.NonParallel.csproj
+++ b/AgileMapper.UnitTests.NonParallel/AgileMapper.UnitTests.NonParallel.csproj
@@ -42,8 +42,8 @@
..\packages\AgileObjects.NetStandardPolyfills.1.4.0\lib\net40\AgileObjects.NetStandardPolyfills.dll
-
- ..\packages\AgileObjects.ReadableExpressions.2.1.1\lib\net40\AgileObjects.ReadableExpressions.dll
+
+ ..\packages\AgileObjects.ReadableExpressions.2.3.2\lib\net40\AgileObjects.ReadableExpressions.dll
diff --git a/AgileMapper.UnitTests.NonParallel/packages.config b/AgileMapper.UnitTests.NonParallel/packages.config
index 4f52878b7..64734ef6e 100644
--- a/AgileMapper.UnitTests.NonParallel/packages.config
+++ b/AgileMapper.UnitTests.NonParallel/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/AgileMapper.UnitTests.Orms.EfCore2/WhenCreatingProjections.cs b/AgileMapper.UnitTests.Orms.EfCore2/WhenCreatingProjections.cs
index f7d7f559f..e3ab13636 100644
--- a/AgileMapper.UnitTests.Orms.EfCore2/WhenCreatingProjections.cs
+++ b/AgileMapper.UnitTests.Orms.EfCore2/WhenCreatingProjections.cs
@@ -1,5 +1,7 @@
namespace AgileObjects.AgileMapper.UnitTests.Orms.EfCore2
{
+ using System.Collections.Generic;
+ using System.Linq;
using System.Threading.Tasks;
using Common;
using Infrastructure;
@@ -49,5 +51,22 @@ public Task ShouldReuseACachedProjectionMapper()
mapper.RootMapperCountShouldBeOne();
});
}
+
+ [Fact]
+ public Task ShouldMapAQueryableAsAnEnumerable()
+ {
+ return RunTest(async (context, mapper) =>
+ {
+ await context.BoolItems.AddRangeAsync(new PublicBool { Value = true }, new PublicBool { Value = false });
+ await context.SaveChangesAsync();
+
+ var result = mapper
+ .Map(context.BoolItems.Where(bi => bi.Value))
+ .ToANew>();
+
+ result.ShouldNotBeNull();
+ result.ShouldHaveSingleItem().Value.ShouldBeTrue();
+ });
+ }
}
}
diff --git a/AgileMapper.UnitTests/AgileMapper.UnitTests.csproj b/AgileMapper.UnitTests/AgileMapper.UnitTests.csproj
index 8d6904379..ef3d3d7fe 100644
--- a/AgileMapper.UnitTests/AgileMapper.UnitTests.csproj
+++ b/AgileMapper.UnitTests/AgileMapper.UnitTests.csproj
@@ -44,8 +44,8 @@
..\packages\AgileObjects.NetStandardPolyfills.1.4.0\lib\net40\AgileObjects.NetStandardPolyfills.dll
-
- ..\packages\AgileObjects.ReadableExpressions.2.1.1\lib\net40\AgileObjects.ReadableExpressions.dll
+
+ ..\packages\AgileObjects.ReadableExpressions.2.3.2\lib\net40\AgileObjects.ReadableExpressions.dll
..\packages\Microsoft.Extensions.Primitives.2.0.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll
@@ -103,6 +103,9 @@
+
+
+
@@ -111,6 +114,12 @@
+
+
+
+
+
+
@@ -144,6 +153,7 @@
+
@@ -219,7 +229,9 @@
+
+
@@ -301,6 +313,7 @@
+
diff --git a/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringDataSourcesInline.cs b/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringDataSourcesInline.cs
index 1d398662d..250f4af91 100644
--- a/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringDataSourcesInline.cs
+++ b/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringDataSourcesInline.cs
@@ -7,7 +7,9 @@
using Common;
using TestClasses;
#if !NET35
+ using NetStandardPolyfills;
using Xunit;
+ using static System.Linq.Expressions.Expression;
#else
using Fact = NUnit.Framework.TestAttribute;
@@ -317,6 +319,194 @@ public void ShouldApplyDifferingTargetTypeInlineDataSourceMemberConfig()
}
}
+ [Fact]
+ public void ShouldApplyAnInlineNullCheckedArrayIndexDataSource()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var source = new PublicProperty[]>
+ {
+ Value = new[]
+ {
+ new PublicField { Value = new Address { Line1 = "1.1" } },
+ new PublicField { Value = new Address { Line1 = "1.2" } }
+ }
+ };
+
+ var result = mapper.Map(source).ToANew>(cfg => cfg
+ .Map(s => s.Value[1].Value, t => t.Value));
+
+ result.Value.ShouldNotBeNull();
+ result.Value.Line1.ShouldBe("1.2");
+
+ var nullArraySource = new PublicProperty[]> { Value = null };
+
+ var nullArrayResult = mapper.Map(nullArraySource).ToANew>(cfg => cfg
+ .Map(s => s.Value[1].Value, t => t.Value));
+
+ nullArrayResult.Value.ShouldBeNull();
+
+ var tooSmallArraySource = new PublicProperty[]>
+ {
+ Value = new[]
+ {
+ new PublicField { Value = new Address { Line1 = "1.1" } }
+ }
+ };
+
+ var tooSmallArrayResult = mapper.Map(tooSmallArraySource).ToANew>(cfg => cfg
+ .Map(s => s.Value[1].Value, t => t.Value));
+
+ tooSmallArrayResult.Value.ShouldBeNull();
+
+ var nullArrayObjectSource = new PublicProperty[]>
+ {
+ Value = new[]
+ {
+ new PublicField { Value = new Address { Line1 = "1.1" } },
+ new PublicField { Value = null }
+ }
+ };
+
+ var nullArrayObjectResult = mapper.Map(nullArrayObjectSource).ToANew>(cfg => cfg
+ .Map(s => s.Value[1].Value, t => t.Value));
+
+ nullArrayObjectResult.Value.ShouldBeNull();
+ }
+ }
+
+#if !NET35
+ // System.Linq.Expressions.Expression.MakeIndex() is missing in .NET 3.5, so not much danger of this configuration:
+ [Fact]
+ public void ShouldApplyAnInlineNullCheckedIntKeyedIndexDataSource()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var source = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ [0] = new PublicField { Value = new Address { Line1 = "1.1" } },
+ [1] = new PublicField { Value = new Address { Line1 = "1.2" } }
+ }
+ };
+
+ var sourceParameter = Parameter(source.GetType(), "s");
+ var sourceValueProperty = Property(sourceParameter, "Value");
+ var sourceValueIndexer = sourceValueProperty.Type.GetPublicInstanceProperty("Item");
+ var sourceValueIndex = MakeIndex(sourceValueProperty, sourceValueIndexer, new[] { Constant(1) });
+
+ var sourceLambda = Lambda>>, Address>>(
+ Field(sourceValueIndex, "Value"),
+ sourceParameter);
+
+ var result = mapper.Map(source).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ result.Value.ShouldNotBeNull();
+ result.Value.Line1.ShouldBe("1.2");
+
+ var nullIndexerSource = new PublicProperty>> { Value = null };
+
+ var nullIndexerResult = mapper.Map(nullIndexerSource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ nullIndexerResult.Value.ShouldBeNull();
+
+ var noEntrySource = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ [0] = new PublicField { Value = new Address { Line1 = "1.1" } }
+ }
+ };
+
+ var noEntryResult = mapper.Map(noEntrySource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ noEntryResult.Value.ShouldBeNull();
+
+ var nullIndexedObjectSource = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ [0] = new PublicField { Value = new Address { Line1 = "1.1" } },
+ [1] = new PublicField { Value = null }
+ }
+ };
+
+ var nullIndexedObjectResult = mapper.Map(nullIndexedObjectSource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ nullIndexedObjectResult.Value.ShouldBeNull();
+ }
+ }
+
+ [Fact]
+ public void ShouldApplyAnInlineNullCheckedStringKeyedIndexDataSource()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var source = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ ["A"] = new PublicField { Value = new Address { Line1 = "1.1" } },
+ ["B"] = new PublicField { Value = new Address { Line1 = "1.2" } }
+ }
+ };
+
+ var sourceParameter = Parameter(source.GetType(), "s");
+ var sourceValueProperty = Property(sourceParameter, "Value");
+ var sourceValueIndexer = sourceValueProperty.Type.GetPublicInstanceProperty("Item");
+ var sourceValueIndex = MakeIndex(sourceValueProperty, sourceValueIndexer, new[] { Constant("B") });
+
+ var sourceLambda = Lambda>>, Address>>(
+ Field(sourceValueIndex, "Value"),
+ sourceParameter);
+
+ var result = mapper.Map(source).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ result.Value.ShouldNotBeNull();
+ result.Value.Line1.ShouldBe("1.2");
+
+ var nullIndexerSource = new PublicProperty>> { Value = null };
+
+ var nullIndexerResult = mapper.Map(nullIndexerSource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ nullIndexerResult.Value.ShouldBeNull();
+
+ var noEntrySource = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ ["A"] = new PublicField { Value = new Address { Line1 = "1.1" } }
+ }
+ };
+
+ var noEntryResult = mapper.Map(noEntrySource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ noEntryResult.Value.ShouldBeNull();
+
+ var nullIndexedObjectSource = new PublicProperty>>
+ {
+ Value = new PublicIndex>
+ {
+ ["A"] = new PublicField { Value = new Address { Line1 = "1.1" } },
+ ["B"] = new PublicField { Value = null }
+ }
+ };
+
+ var nullIndexedObjectResult = mapper.Map(nullIndexedObjectSource).ToANew>(cfg => cfg
+ .Map(sourceLambda, t => t.Value));
+
+ nullIndexedObjectResult.Value.ShouldBeNull();
+ }
+ }
+#endif
[Fact]
public void ShouldHandleANullSourceMember()
{
diff --git a/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringStringFormattingInline.cs b/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringStringFormattingInline.cs
index 0f19d9ceb..c923a849a 100644
--- a/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringStringFormattingInline.cs
+++ b/AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringStringFormattingInline.cs
@@ -1,5 +1,6 @@
namespace AgileObjects.AgileMapper.UnitTests.Configuration.Inline
{
+ using System;
using AgileMapper.Configuration;
using Common;
using TestClasses;
@@ -43,6 +44,30 @@ public void ShouldFormatDoublesWithDecimalPlacesInline()
}
}
+ // See https://github.com/agileobjects/AgileMapper/issues/149
+ [Fact]
+ public void ShouldFormatNullableDateTimesInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var result1 = mapper
+ .Map(new PublicProperty { Value = DateTime.Today })
+ .ToANew>(cfg => cfg
+ .WhenMapping
+ .StringsFrom(c => c.FormatUsing("yyyy MM dd")));
+
+ result1.Value.ShouldBe(DateTime.Today.ToString("yyyy MM dd"));
+
+ var result2 = mapper
+ .Map(new PublicProperty { Value = null })
+ .ToANew>();
+
+ result2.Value.ShouldBeNull();
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+ }
+ }
+
[Fact]
public void ShouldErrorIfUnformattableTypeSpecifiedInline()
{
diff --git a/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMemberInlineIncorrectly.cs b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMemberInlineIncorrectly.cs
new file mode 100644
index 000000000..ca466a297
--- /dev/null
+++ b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMemberInlineIncorrectly.cs
@@ -0,0 +1,36 @@
+namespace AgileObjects.AgileMapper.UnitTests.Configuration.Inline
+{
+ using AgileMapper.Configuration;
+ using Common;
+ using TestClasses;
+#if !NET35
+ using Xunit;
+#else
+ using Fact = NUnit.Framework.TestAttribute;
+
+ [NUnit.Framework.TestFixture]
+#endif
+ public class WhenIgnoringSourceMemberInlineIncorrectly
+ {
+ [Fact]
+ public void ShouldErrorIfDuplicateSourceIgnoreIsConfiguredInline()
+ {
+ var ignoreEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From>()
+ .IgnoreSource(pf => pf.Value);
+
+ mapper
+ .Map(new PublicField { Value = 123 })
+ .ToANew>(cfg => cfg
+ .IgnoreSource(pf => pf.Value));
+ }
+ });
+
+ ignoreEx.Message.ShouldContain("has already been ignored");
+ }
+ }
+}
diff --git a/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersByValueFilterInline.cs b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersByValueFilterInline.cs
new file mode 100644
index 000000000..9509688e9
--- /dev/null
+++ b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersByValueFilterInline.cs
@@ -0,0 +1,301 @@
+namespace AgileObjects.AgileMapper.UnitTests.Configuration.Inline
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using AgileMapper.Extensions.Internal;
+ using AgileObjects.AgileMapper.Configuration;
+ using Common;
+ using TestClasses;
+#if !NET35
+ using Xunit;
+#else
+ using Fact = NUnit.Framework.TestAttribute;
+
+ [NUnit.Framework.TestFixture]
+#endif
+ public class WhenIgnoringSourceMembersByValueFilterInline
+ {
+ [Fact]
+ public void ShouldIgnoreSourceValuesByMultiClauseTypedValueFiltersOnline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var matchingIntResult = mapper
+ .Map(new PublicField { Value = 123 })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c =>
+ c.If(str => str == "123") || c.If(i => i == 123) ||
+ (c.If(str => str != "999") && !c.If(dt => dt == DateTime.Today))));
+
+ matchingIntResult.ShouldNotBeNull();
+ matchingIntResult.Value.ShouldBeDefault();
+
+ var matchingStringResult = mapper
+ .Map(new PublicField { Value = "123" })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c =>
+ c.If(str => str == "123") || c.If(i => i == 123) ||
+ (c.If(str => str != "999") && !c.If(dt => dt == DateTime.Today))));
+
+ matchingStringResult.ShouldNotBeNull();
+ matchingStringResult.Value.ShouldBeNull();
+
+ var nonMatchingIntResult = mapper
+ .Map(new PublicField { Value = 456 })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c =>
+ c.If(str => str == "123") || c.If(i => i == 123) ||
+ (c.If(str => str != "999") && !c.If(dt => dt == DateTime.Today))));
+
+ nonMatchingIntResult.ShouldNotBeNull();
+ nonMatchingIntResult.Value.ShouldBe(456);
+
+ var nonMatchingStringResult = mapper
+ .Map(new PublicField { Value = "999" })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c =>
+ c.If(str => str == "123") || c.If(i => i == 123) ||
+ (c.If(str => str != "999") && !c.If(dt => dt == DateTime.Today))));
+
+ nonMatchingStringResult.ShouldNotBeNull();
+ nonMatchingStringResult.Value.ShouldBe("999");
+
+ var nonMatchingTypeResult = mapper
+ .Map(new PublicField { Value = 123L })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c =>
+ c.If(str => str == "123") || c.If(i => i == 123) ||
+ (c.If(str => str != "999") && !c.If(dt => dt == DateTime.Today))));
+
+ nonMatchingTypeResult.ShouldNotBeNull();
+ nonMatchingTypeResult.Value.ShouldBe("123");
+ }
+ }
+
+ [Fact]
+ public void ShouldHandleNullMemberInANestedSourceValueFilterInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var result = mapper
+ .Map(new List
+ {
+ new Customer { Name = "Customer 1", Address = new Address { Line1 = "1 Street" } },
+ new MysteryCustomer { Name = "Customer 2"}
+ })
+ .ToANew>(cfg => cfg
+ .IgnoreSources(s => s.If(c => c.Address.Line1.Length < 2)));
+
+ result.ShouldNotBeNull();
+ result.ShouldHaveSingleItem();
+ result.First().Name.ShouldBe("Customer 1");
+ result.First().AddressLine1.ShouldBe("1 Street");
+ }
+ }
+
+ [Fact]
+ public void ShouldFilterAnEnumerableSourceValueConditionallyInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From>()
+ .Over>>()
+ .Map(ctx => ctx.Source.Value1)
+ .To(t => t.Value)
+ .But
+ .If(ctx => ctx.Source.Value1.None())
+ .Map(ctx => ctx.Source.Value2)
+ .To(t => t.Value);
+
+ var target = new PublicProperty>();
+
+ var bothValuesSource = new PublicTwoFields
+ {
+ Value1 = new[] { new Product { ProductId = "111" } },
+ Value2 = new[] { new Product { ProductId = "222" } }
+ };
+
+ mapper.Map(bothValuesSource).Over(target);
+
+ target.Value.ShouldHaveSingleItem().ProductId.ShouldBe("111");
+ target.Value.Clear();
+
+ var emptyValue1Source = new PublicTwoFields
+ {
+ Value1 = Enumerable.EmptyArray,
+ Value2 = new[] { new Product { ProductId = "222" } }
+ };
+
+ mapper.Map(emptyValue1Source).Over(target);
+
+ target.Value.ShouldHaveSingleItem().ProductId.ShouldBe("222");
+ target.Value.Clear();
+
+ mapper
+ .Map(bothValuesSource)
+ .Over(target, cfg => cfg
+ .IgnoreSources(s => s.If(ps => ps[0].ProductId == "111")));
+
+ target.Value.ShouldBeEmpty();
+ target.Value = null;
+
+ mapper
+ .Map(bothValuesSource)
+ .Over(target, cfg => cfg
+ .IgnoreSources(s => s.If(ps => ps[0].ProductId == "111")));
+
+ target.Value.ShouldBeNull();
+ }
+ }
+
+ [Fact]
+ public void ShouldExtendSourceValueFilterConfiguration()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From>()
+ .Over>()
+ .IgnoreSources(c => c.If(i => i < 10));
+
+ var result1 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 4, Value2 = 12L })
+ .Over(new PublicTwoFields(), cfg => cfg
+ .IgnoreSources(c => c.If(l => l > 10L)));
+
+ result1.Value1.ShouldBeDefault(); // int < 10
+ result1.Value2.ShouldBeDefault(); // long > 10
+
+ var result2 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 20, Value2 = 15L })
+ .Over(new PublicTwoFields(), cfg => cfg
+ .IgnoreSources(c => c.If(l => l > 10L)));
+
+ result2.Value1.ShouldBe(20);
+ result2.Value2.ShouldBeDefault(); // long > 10
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+
+ var result3 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 20, Value2 = 11L })
+ .Over(new PublicTwoFields(), cfg => cfg
+ .IgnoreSources(c => c.If(i => i < 25))
+ .And
+ .IgnoreSources(c => c.If(l => l > 12L)));
+
+ result3.Value1.ShouldBeDefault(); // int < 25
+ result3.Value2.ShouldBe(11);
+
+ mapper.InlineContexts().Count.ShouldBe(2);
+ }
+ }
+
+ [Fact]
+ public void ShouldReplaceASourceValueFilterWithAConditionalFilterInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .IgnoreSources(c => c.If(value => value % 2 == 0));
+
+ var evenValueSource = new PublicField { Value = 8 };
+ var eventValueResult = mapper.Map(evenValueSource).ToANew>();
+
+ eventValueResult.ShouldNotBeNull();
+ eventValueResult.Value.ShouldBeDefault();
+
+ var oddValueSource = new PublicField { Value = 5 };
+ var oddValueResult = mapper.Map(oddValueSource).ToANew>();
+
+ oddValueResult.ShouldNotBeNull();
+ oddValueResult.Value.ShouldBe(5);
+
+ var inlineFilterSmallEvenValueResult = mapper
+ .Map(evenValueSource)
+ .ToANew>(cfg => cfg
+ .If(ctx => ctx.Source.Value > 10)
+ .IgnoreSources(c => c.If(value => value % 2 == 0)));
+
+ inlineFilterSmallEvenValueResult.ShouldNotBeNull();
+ inlineFilterSmallEvenValueResult.Value.ShouldBe(8);
+
+ var inlineFilterLargeEvenValueResult = mapper
+ .Map(new PublicField { Value = 16 })
+ .ToANew>(cfg => cfg
+ .If(ctx => ctx.Source.Value > 10)
+ .IgnoreSources(c => c.If(value => value % 2 == 0)));
+
+ inlineFilterLargeEvenValueResult.ShouldNotBeNull();
+ inlineFilterLargeEvenValueResult.Value.ShouldBeDefault();
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+ }
+ }
+
+ [Fact]
+ public void ShouldReplaceAMultiClauseSourceValueFilterWithAConditionalFilterInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .IgnoreSources(c => c.If(value => value > 3) && c.If(value => value < 8));
+
+ var filteredValueSource = new PublicField { Value = 6 };
+ var filteredValueResult = mapper.Map(filteredValueSource).ToANew>();
+
+ filteredValueResult.ShouldNotBeNull();
+ filteredValueResult.Value.ShouldBeDefault();
+
+ var unfilteredValueSource = new PublicField { Value = 2 };
+ var unfilteredValueResult = mapper.Map(unfilteredValueSource).ToANew>();
+
+ unfilteredValueResult.ShouldNotBeNull();
+ unfilteredValueResult.Value.ShouldBe(2);
+
+ var inlineUnfilteredValueResult = mapper
+ .Map(filteredValueSource)
+ .ToANew>(cfg => cfg
+ .If(ctx => ctx.Source.Value != 6)
+ .IgnoreSources(c => c.If(value => value > 3) && c.If(value => value < 8)));
+
+ inlineUnfilteredValueResult.ShouldNotBeNull();
+ inlineUnfilteredValueResult.Value.ShouldBe(6);
+
+ var inlineFilteredValueResult = mapper
+ .Map(new PublicField { Value = 7 })
+ .ToANew>(cfg => cfg
+ .If(ctx => ctx.Source.Value != 6)
+ .IgnoreSources(c => c.If(value => value > 3) && c.If(value => value < 8)));
+
+ inlineFilteredValueResult.ShouldNotBeNull();
+ inlineFilteredValueResult.Value.ShouldBeDefault();
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+ }
+ }
+
+ [Fact]
+ public void ShouldErrorIfDuplicateSourceValueFilterConfiguredInline()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .IgnoreSources(c => c.If(value => value == 555));
+
+ mapper
+ .Map(new PublicField())
+ .ToANew>(cfg => cfg
+ .IgnoreSources(c => c.If(value => value == 555)));
+ }
+ });
+
+ configEx.Message.ShouldContain("Source filter");
+ configEx.Message.ShouldContain("If(value => value == 555)");
+ configEx.Message.ShouldContain("already been configured");
+ }
+ }
+}
diff --git a/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersInline.cs b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersInline.cs
new file mode 100644
index 000000000..b4cf2f8d5
--- /dev/null
+++ b/AgileMapper.UnitTests/Configuration/Inline/WhenIgnoringSourceMembersInline.cs
@@ -0,0 +1,86 @@
+namespace AgileObjects.AgileMapper.UnitTests.Configuration.Inline
+{
+ using Common;
+ using TestClasses;
+#if !NET35
+ using Xunit;
+#else
+ using Fact = NUnit.Framework.TestAttribute;
+
+ [NUnit.Framework.TestFixture]
+#endif
+ public class WhenIgnoringSourceMembersInline
+ {
+ [Fact]
+ public void ShouldFilterASourceMemberConditionallyInline()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var matchingResult = mapper
+ .Map(new CustomerViewModel { Discount = 0.5 })
+ .ToANew(cfg => cfg
+ .If(ctx => ctx.Source.Discount > 0.3)
+ .IgnoreSource(cvm => cvm.Discount));
+
+ matchingResult.Discount.ShouldBeDefault();
+
+ var nonMatchingResult = mapper
+ .Map(new CustomerViewModel { Discount = 0.2 })
+ .ToANew(cfg => cfg
+ .If(ctx => ctx.Source.Discount > 0.3)
+ .IgnoreSource(cvm => cvm.Discount));
+
+ nonMatchingResult.Discount.ShouldBe(0.2m);
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+ }
+ }
+
+ [Fact]
+ public void ShouldExtendSourceMemberFilterConfiguration()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From>()
+ .To>()
+ .If((sptf, tptf) => sptf.Value1 < 5)
+ .IgnoreSource(sptf => sptf.Value1); // Ignore source.Value1 < 5
+
+ var result1 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 4, Value2 = 8 })
+ .OnTo(new PublicTwoFields(), c => c
+ .If((sptf, tptf) => sptf.Value2 <= 10)
+ .IgnoreSource(sptf => sptf.Value2)); // Ignore source.Value2 <= 10
+
+ result1.Value1.ShouldBeDefault();
+ result1.Value2.ShouldBeDefault();
+
+ var result2 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 5, Value2 = 7 })
+ .OnTo(new PublicTwoFields(), c => c
+ .If((sptf, tptf) => sptf.Value2 <= 10)
+ .IgnoreSource(sptf => sptf.Value2)); // Ignore source.Value2 <= 10
+
+ result2.Value1.ShouldBe(5);
+ result2.Value2.ShouldBeDefault();
+
+ mapper.InlineContexts().ShouldHaveSingleItem();
+
+ var result3 = mapper
+ .Map(new PublicTwoFieldsStruct { Value1 = 5, Value2 = 11 })
+ .OnTo(new PublicTwoFields(), c => c
+ .If((sptf, tptf) => sptf.Value1 >= 3)
+ .IgnoreSource(sptf => sptf.Value1) // Ignore source.Value1 >= 3
+ .And
+ .If((sptf, tptf) => sptf.Value2 <= 10)
+ .IgnoreSource(sptf => sptf.Value2)); // Ignore source.Value2 < 10
+
+ result3.Value1.ShouldBeDefault();
+ result3.Value2.ShouldBe(11);
+
+ mapper.InlineContexts().Count.ShouldBe(2);
+ }
+ }
+ }
+}
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs
index be0810cc8..635d041ce 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs
@@ -148,9 +148,36 @@ public void ShouldApplyMultipleConfiguredMembersBySourceType()
}
}
+ [Fact]
+ public void ShouldAllowConditionTypeTestsWhenMappingFromAnInterface()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var sourceData = default(Issue146.Source.Data);
+
+ mapper.WhenMapping
+ .From().To()
+ .Map(s => s.Empty, t => t.Info);
+
+ mapper.WhenMapping
+ .From().To()
+ .After
+ .MappingEnds
+ .If(ctx => ctx.Source is Issue146.Source.Data)
+ .Call(ctx => sourceData = (Issue146.Source.Data)ctx.Source);
+
+ var source = new Issue146.Source.Container("xxx");
+ var result = mapper.Map(source).ToANew();
+
+ result.ShouldNotBeNull();
+ sourceData.ShouldNotBeNull();
+ sourceData.ShouldBeSameAs(source.Empty);
+ }
+ }
+
// See https://github.com/agileobjects/AgileMapper/issues/111
[Fact]
- public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeConstant()
+ public void ShouldConditionallyApplyAToTargetSimpleTypeConstant()
{
using (var mapper = Mapper.CreateNew())
{
@@ -168,7 +195,7 @@ public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeConstant()
}
[Fact]
- public void ShouldApplyAToTargetConfiguredSimpleTypeConstant()
+ public void ShouldConditionallyApplyAToTargetSimpleType()
{
using (var mapper = Mapper.CreateNew())
{
@@ -185,7 +212,7 @@ public void ShouldApplyAToTargetConfiguredSimpleTypeConstant()
}
[Fact]
- public void ShouldConditionallyApplyAToTargetConfiguredNestedSimpleTypeExpression()
+ public void ShouldConditionallyApplyAToTargetNestedSimpleTypeExpression()
{
using (var mapper = Mapper.CreateNew())
{
@@ -209,7 +236,7 @@ public void ShouldConditionallyApplyAToTargetConfiguredNestedSimpleTypeExpressio
}
[Fact]
- public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeExpressionInAComplexTypeList()
+ public void ShouldConditionallyApplyAToTargetSimpleTypeExpressionToAComplexTypeListMember()
{
using (var mapper = Mapper.CreateNew())
{
@@ -258,6 +285,27 @@ public void ShouldConditionallyApplyAConfiguredMember()
}
}
+ [Fact]
+ public void ShouldNotOverwriteATargetWithNoMatchingSourceMember()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From>()
+ .To>()
+ .If(ctx => ctx.Source.Value1 > 100)
+ .Map((ptf, pf) => ptf.Value1)
+ .To(pf => pf.Value);
+
+ var source = new PublicTwoFieldsStruct { Value1 = 50 };
+ var target = new PublicField { Value = "Value!" };
+
+ mapper.Map(source).Over(target);
+
+ target.Value.ShouldBe("Value!");
+ }
+ }
+
[Fact]
public void ShouldConditionallyApplyMultipleConfiguredMembers()
{
@@ -509,7 +557,7 @@ public void ShouldApplyAConfiguredExpressionToAnArray()
.From>()
.To>()
#if NETCOREAPP2_0
- .Map(ctx => ctx.Source.Value.Split(':', System.StringSplitOptions.None))
+ .Map(ctx => ctx.Source.Value.Split(':', StringSplitOptions.None))
#else
.Map(ctx => ctx.Source.Value.Split(':'))
#endif
@@ -1161,9 +1209,32 @@ public void ShouldAllowIdAndIdentifierConfiguration()
}
}
+ // See https://github.com/agileobjects/AgileMapper/issues/146
+ [Fact]
+ public void ShouldApplyAConfiguredSourceInterfaceMember()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To()
+ .Map(ctx => ctx.Source.Empty).To(tgt => tgt.Info);
+
+ var source = new Issue146.Source.Container("12321") { Name = "input" };
+ var result = mapper.Map(source).ToANew();
+
+ result.ShouldNotBeNull();
+ result.Name.ShouldBe("input");
+ result.Info.ShouldNotBeNull();
+ result.Info.Id.ShouldBe("12321");
+
+ // Source has a .Value member, but we don't runtime-type interfaces
+ result.Info.Value.ShouldBeNull();
+ }
+ }
+
// See https://github.com/agileobjects/AgileMapper/issues/64
[Fact]
- public void ShouldApplyAConfiguredRootSource()
+ public void ShouldApplyAConfiguredToTargetDataSource()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1185,7 +1256,7 @@ public void ShouldApplyAConfiguredRootSource()
}
[Fact]
- public void ShouldApplyANestedOverwriteConfiguredRootSource()
+ public void ShouldApplyANestedOverwriteConfiguredToTargetDataSource()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1345,7 +1416,7 @@ public void ShouldApplyAConfiguredRootSourceToANestedMember()
}
[Fact]
- public void ShouldApplyAConfiguredRootSourceToAnEnumerableElement()
+ public void ShouldApplyAToTargetComplexTypeToAComplexTypeEnumerableElement()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1376,7 +1447,7 @@ public void ShouldApplyAConfiguredRootSourceToAnEnumerableElement()
}
[Fact]
- public void ShouldApplyAConfiguredEnumerableRootSource()
+ public void ShouldApplyAToTargetComplexTypeEnumerable()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1413,7 +1484,7 @@ public void ShouldApplyAConfiguredEnumerableRootSource()
}
[Fact]
- public void ShouldApplyMultipleConfiguredComplexTypeRootSources()
+ public void ShouldApplyMultipleToTargetComplexTypes()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1440,7 +1511,7 @@ public void ShouldApplyMultipleConfiguredComplexTypeRootSources()
}
[Fact]
- public void ShouldApplyMultipleConfiguredEnumerableRootSources()
+ public void ShouldApplyMultipleToTargetSimpleTypeEnumerables()
{
using (var mapper = Mapper.CreateNew())
{
@@ -1465,6 +1536,30 @@ public void ShouldApplyMultipleConfiguredEnumerableRootSources()
}
}
+ // See https://github.com/agileobjects/AgileMapper/issues/145
+ [Fact]
+ public void ShouldHandleNullToTargetDataSourceNestedMembers()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To()
+ .Map((srcData, tgtData) => srcData.cont).ToTarget();
+
+ var source = new Issue145.DataSource
+ {
+ cont = new Issue145.DataSourceContainer()
+ };
+
+ var result = mapper.Map(source).ToANew();
+
+ result.ShouldNotBeNull();
+ result.ids.ShouldBeNull();
+ result.res.ShouldBeNull();
+ result.oth.ShouldBeNull();
+ }
+ }
+
// See https://github.com/agileobjects/AgileMapper/issues/125
[Fact]
public void ShouldHandleDeepNestedRuntimeTypedMembersWithACachedMappingPlan()
@@ -1545,6 +1640,42 @@ public void ShouldHandleDeepNestedRuntimeTypedMembersWithACachedMappingPlan()
}
}
+ [Fact]
+ public void ShouldApplyAToTargetSimpleTypeToANestedComplexTypeMember()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .Map(ctx => PublicEnumerable.Parse(ctx.Source)).ToTarget();
+
+ mapper.GetPlanFor>().ToANew>>();
+
+ var source = new PublicField { Value = "1,2,3" };
+ var result = mapper.Map(source).ToANew>>();
+
+ result.ShouldNotBeNull();
+ result.Value.ShouldNotBeNull();
+ result.Value.ShouldBe(1, 2, 3);
+ }
+ }
+
+ [Fact]
+ public void ShouldConditionallyApplyAToTargetSimpleTypeToANestedComplexTypeMember()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .If(cxt => cxt.Source.Contains(','))
+ .Map(ctx => PublicEnumerable.Parse(ctx.Source)).ToTarget();
+
+ mapper.GetPlanFor>().ToANew>>();
+ }
+ }
+
+ #region Helper Classes
+
internal class IdTester
{
public int ClassId { get; set; }
@@ -1718,5 +1849,111 @@ public class ParamDef
// ReSharper restore AutoPropertyCanBeMadeGetOnly.Local
// ReSharper restore MemberCanBePrivate.Local
// ReSharper restore CollectionNeverQueried.Local
+
+ // ReSharper disable InconsistentNaming
+ internal static class Issue145
+ {
+ public class IdsSource
+ {
+ public string Ids { get; set; }
+ }
+
+ public class ResultSource
+ {
+ public string Result { get; set; }
+ }
+
+ public class OtherDataSource
+ {
+ public string COD { get; set; }
+ }
+
+ public class DataSourceContainer
+ {
+
+ public IdsSource ids;
+ public ResultSource res;
+ public OtherDataSource oth;
+ }
+
+ public class DataSource
+ {
+ public DataSourceContainer cont;
+ }
+
+ public class IdsTarget
+ {
+ public string Ids { get; set; }
+ }
+
+ public class ResultTarget
+ {
+ public string Result { get; set; }
+ }
+
+ public class OtherDataTarget
+ {
+ public string COD { get; set; }
+ }
+
+ public class DataTarget
+ {
+ public IdsTarget ids;
+ public ResultTarget res;
+ public OtherDataTarget oth;
+ }
+ }
+ // ReSharper restore InconsistentNaming
+
+ internal static class Issue146
+ {
+ public static class Source
+ {
+ public interface IData
+ {
+ string Id { get; set; }
+ }
+
+ public interface IEmpty : IData { }
+
+ public class Data : IEmpty
+ {
+ public string Id { get; set; }
+
+ public string Value => "Data.Value!";
+ }
+
+ public class Container
+ {
+ public Container(string infoId)
+ {
+ Empty = new Data { Id = infoId };
+ }
+
+ public string Name { get; set; }
+
+ public IEmpty Empty { get; }
+ }
+ }
+
+ public static class Target
+ {
+ public class Data
+ {
+ public string Id { get; set; }
+
+ public string Value { get; set; }
+ }
+
+ public class Cont
+ {
+ public Data Info { get; set; }
+
+ public string Name { get; set; }
+ }
+ }
+ }
+
+ #endregion
}
}
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringEntityMapping.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringEntityMapping.cs
index 558c457fd..c15b593b6 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringEntityMapping.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringEntityMapping.cs
@@ -1,5 +1,6 @@
namespace AgileObjects.AgileMapper.UnitTests.Configuration
{
+ using System;
using AgileMapper.Configuration;
using Common;
using TestClasses;
@@ -73,6 +74,43 @@ public void ShouldIgnoreEntityKeysForASpecificSourceAndTargetType()
}
}
+ [Fact]
+ public void ShouldIgnoreEntityKeysForSpecificSourceAndTargetTypes()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var sourceId = new { Id = 999 };
+ var sourceIdAndDate = new { Id = 999, DateCreated = DateTime.Now };
+
+ mapper.WhenMapping.MapEntityKeys();
+
+ mapper.WhenMapping
+ .From(sourceId).To()
+ .IgnoreEntityKeys();
+
+ mapper.WhenMapping
+ .From(sourceIdAndDate).To()
+ .IgnoreEntityKeys();
+
+ var sourceIdResult = mapper.Map(sourceId).ToANew();
+
+ sourceIdResult.Id.ShouldBeDefault();
+
+ var sourceIdAndDateResult = mapper.Map(sourceIdAndDate).ToANew();
+
+ sourceIdAndDateResult.Id.ShouldBeDefault();
+ sourceIdAndDateResult.DateCreated.ShouldBe(sourceIdAndDate.DateCreated);
+
+ var nonMatchingSourceResult = mapper.Map(new { Id = 987, Name = "Fred" }).ToANew();
+
+ nonMatchingSourceResult.Id.ShouldBe(987);
+
+ var nonMatchingTargetResult = mapper.Map(sourceId).ToANew();
+
+ nonMatchingTargetResult.Id.ShouldBe(999);
+ }
+ }
+
[Fact]
public void ShouldErrorIfDuplicateMapKeysConfigured()
{
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringEnumMapping.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringEnumMapping.cs
index f0f313008..d8b322d8b 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringEnumMapping.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringEnumMapping.cs
@@ -33,6 +33,43 @@ public void ShouldPairEnumMembers()
}
}
+ // See https://github.com/agileobjects/AgileMapper/issues/138
+ [Fact]
+ public void ShouldApplyEnumPairsToRootMappings()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .PairEnum(PaymentTypeUk.Cheque).With(PaymentTypeUs.Check);
+
+ var ukChequeResult = mapper.Map(PaymentTypeUk.Cheque).ToANew();
+
+ ukChequeResult.ShouldBe(PaymentTypeUs.Check);
+
+ var usCheckResult = mapper.Map(PaymentTypeUs.Check).ToANew();
+
+ usCheckResult.ShouldBe(PaymentTypeUk.Cheque);
+ }
+ }
+
+ [Fact]
+ public void ShouldApplyEnumPairsToNullableRootMappings()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .PairEnum(PaymentTypeUk.Cheque).With(PaymentTypeUs.Check);
+
+ var ukChequeResult = mapper.Map(PaymentTypeUk.Cheque).ToANew();
+
+ ukChequeResult.ShouldBe(PaymentTypeUs.Check);
+
+ var usCheckResult = mapper.Map((PaymentTypeUs)1234).ToANew();
+
+ usCheckResult.ShouldBeNull();
+ }
+ }
+
[Fact]
public void ShouldAllowMultipleSourceToSingleTargetPairing()
{
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringMappingCallbacks.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringMappingCallbacks.cs
index 9d1aad259..24d48f843 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringMappingCallbacks.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringMappingCallbacks.cs
@@ -264,6 +264,28 @@ public void ShouldExecuteAPostMappingCallbackForASpecifiedTargetTypeConditionall
}
}
+ [Fact]
+ public void ShouldExecuteGlobalPreAndPostMappingCallbacksInARootNullableEnumMapping()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ var counter = 0;
+
+ mapper.Before
+ .MappingBegins
+ .Call(ctx => ++counter)
+ .And
+ .After
+ .MappingEnds
+ .Call(ctx => ++counter);
+
+ var result = mapper.Map("Mrs").ToANew();
+
+ result.ShouldBe(Title.Mrs);
+ counter.ShouldBe(2);
+ }
+ }
+
[Fact]
public void ShouldRestrictAPostMappingCallbackByTargetType()
{
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringObjectTrackingIncorrectly.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringObjectTrackingIncorrectly.cs
index 43bc28176..6164042ae 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringObjectTrackingIncorrectly.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringObjectTrackingIncorrectly.cs
@@ -125,13 +125,12 @@ public void ShouldErrorIfGlobalObjectTrackingDisabledTwice()
}
[Fact]
- public void ShouldErrorIfObjectTrackingDisabledTwice()
+ public void ShouldErrorIfDuplicateObjectTrackingDisabled()
{
using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping
- .From()
- .To()
+ .From().To()
.DisableObjectTracking();
var configEx = Should.Throw(() =>
@@ -146,5 +145,27 @@ public void ShouldErrorIfObjectTrackingDisabledTwice()
configEx.Message.ShouldContain("PersonViewModel -> Person");
}
}
+
+ [Fact]
+ public void ShouldErrorIfRedundantObjectTrackingDisabled()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .To()
+ .DisableObjectTracking();
+
+ var configEx = Should.Throw(() =>
+ {
+ mapper.WhenMapping
+ .From()
+ .To()
+ .DisableObjectTracking();
+ });
+
+ configEx.Message.ShouldContain("Object tracking is already disabled");
+ configEx.Message.ShouldContain("to Person");
+ }
+ }
}
}
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSources.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSources.cs
index 6a0b23ff0..1df1ff1bf 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSources.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSources.cs
@@ -42,12 +42,10 @@ public void ShouldReverseAConfiguredMemberByMappingScope()
using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping
- .From()
- .To>()
+ .From().To>()
.AutoReverseConfiguredDataSources()
.And
- .Map(ctx => ctx.Source.Id)
- .To(pp => pp.Value);
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value);
var source = new Person { Id = Guid.NewGuid() };
var result = mapper.Map(source).ToANew>();
@@ -60,6 +58,39 @@ public void ShouldReverseAConfiguredMemberByMappingScope()
}
}
+ [Fact]
+ public void ShouldReverseConfiguredMembersByMappingScope()
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources()
+ .And
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value);
+
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources()
+ .And
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value);
+
+ var source = new Person { Id = Guid.NewGuid() };
+
+ var propertyResult = mapper.Map(source).ToANew>();
+ propertyResult.Value.ShouldBe(source.Id);
+
+ var reversePropertyResult = mapper.Map(propertyResult).ToANew();
+ reversePropertyResult.Id.ShouldBe(source.Id);
+
+ var fieldResult = mapper.Map(source).ToANew>();
+ fieldResult.Value.ShouldBe(source.Id);
+
+ var reverseFieldResult = mapper.Map(fieldResult).ToANew();
+ reverseFieldResult.Id.ShouldBe(source.Id);
+ }
+ }
+
[Fact]
public void ShouldReverseAConfiguredMemberByMemberScope()
{
diff --git a/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSourcesIncorrectly.cs b/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSourcesIncorrectly.cs
index b45c36b90..02fdecd06 100644
--- a/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSourcesIncorrectly.cs
+++ b/AgileMapper.UnitTests/Configuration/WhenConfiguringReverseDataSourcesIncorrectly.cs
@@ -14,7 +14,7 @@
public class WhenConfiguringReverseDataSourcesIncorrectly
{
[Fact]
- public void ShouldErrorIfRedundantMappingScopeOptInConfigured()
+ public void ShouldErrorIfGlobalScopeRedundantMappingScopeOptInConfigured()
{
var configEx = Should.Throw(() =>
{
@@ -23,8 +23,7 @@ public void ShouldErrorIfRedundantMappingScopeOptInConfigured()
mapper.WhenMapping
.AutoReverseConfiguredDataSources()
.AndWhenMapping
- .From()
- .To>()
+ .From().To>()
.AutoReverseConfiguredDataSources();
}
});
@@ -34,7 +33,7 @@ public void ShouldErrorIfRedundantMappingScopeOptInConfigured()
}
[Fact]
- public void ShouldErrorIfRedundantMemberScopeOptInConfigured()
+ public void ShouldErrorIfGlobalScopeRedundantMemberScopeOptInConfigured()
{
var configEx = Should.Throw(() =>
{
@@ -43,10 +42,28 @@ public void ShouldErrorIfRedundantMemberScopeOptInConfigured()
mapper.WhenMapping
.AutoReverseConfiguredDataSources()
.AndWhenMapping
- .From()
- .To>()
- .Map(ctx => ctx.Source.Id)
- .To(pp => pp.Value)
+ .From().To>()
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value)
+ .AndViceVersa();
+ }
+ });
+
+ configEx.Message.ShouldContain("reversed");
+ configEx.Message.ShouldContain("enabled by default");
+ }
+
+ [Fact]
+ public void ShouldErrorIfMappingScopeRedundantMemberScopeOptInConfigured()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources()
+ .And
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value)
.AndViceVersa();
}
});
@@ -56,7 +73,63 @@ public void ShouldErrorIfRedundantMemberScopeOptInConfigured()
}
[Fact]
- public void ShouldErrorIfRedundantMappingScopeOptOutConfigured()
+ public void ShouldErrorIfMappingScopeRedundantDerivedMappingScopeOptInConfigured()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources();
+
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources();
+ }
+ });
+
+ configEx.Message.ShouldContain("already enabled");
+ configEx.Message.ShouldContain("Product -> PublicProperty");
+ }
+
+ [Fact]
+ public void ShouldErrorIfGlobalScopeRedundantMappingScopeOptOutConfigured()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .DoNotAutoReverseConfiguredDataSources();
+ }
+ });
+
+ configEx.Message.ShouldContain("data source reversal");
+ configEx.Message.ShouldContain("disabled by default");
+ }
+
+ [Fact]
+ public void ShouldErrorIfGlobalScopeRedundantMemberScopeOptOutConfigured()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .Map(ctx => ctx.Source.Id).To(pp => pp.Value)
+ .ButNotViceVersa();
+ }
+ });
+
+ configEx.Message.ShouldContain("reverse");
+ configEx.Message.ShouldContain("disabled by default");
+ }
+
+ [Fact]
+ public void ShouldErrorIfMappingScopeRedundantMemberScopeOptOutConfigured()
{
var configEx = Should.Throw(() =>
{
@@ -78,27 +151,94 @@ public void ShouldErrorIfRedundantMappingScopeOptOutConfigured()
}
[Fact]
- public void ShouldErrorIfRedundantMemberScopeOptOutConfigured()
+ public void ShouldErrorIfDuplicateMappingScopeOptInConfigured()
+ {
+ var configEx = Should.Throw(() =>
+ {
+ using (var mapper = Mapper.CreateNew())
+ {
+ mapper.WhenMapping
+ .From().To>()
+ .AutoReverseConfiguredDataSources();
+
+ mapper.WhenMapping
+ .From