|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: AgileMapper v1.7 Released |
| 4 | +excerpt: AgileMapper 1.7 is now on NuGet with bug fixes, and some new options for configuring data sources. |
| 5 | +tags: [AgileMapper] |
| 6 | +images_dir: '2020-06-18/' |
| 7 | +--- |
| 8 | + |
| 9 | +_AgileMapper is a powerful and unopinionated object mapper for .NET 3.5+ and .NET Standard 1.0+. It |
| 10 | +flattens, unflattens, deep clones, merges, updates and projects queries. It works without configuration, |
| 11 | +but if needed, is highly and easily configurable._ |
| 12 | + |
| 13 | +AgileMapper 1.7 is now [on NuGet]({{ site.am_nuget }}) with bug fixes, and some new options for |
| 14 | +[configuring data sources]({{ site.am_docs }}/configuration/Member-Values). |
| 15 | + |
| 16 | +## Configuring Complete Type Mappings |
| 17 | + |
| 18 | +AgileMapper does a pretty good job of figuring out how to map a pair of types, but for times when |
| 19 | +types don't match up at all, complete mappings can now be configured. This configuration is applied |
| 20 | +by the mapper whenever the configured type pair is matched: |
| 21 | + |
| 22 | +```csharp |
| 23 | +Mapper.WhenMapping |
| 24 | + .From<Address>().To<AddressDto>() |
| 25 | + .MapInstancesUsing((a, dto) => new AddressDto |
| 26 | + { |
| 27 | + Number = a.HouseNo, |
| 28 | + Line1 = a.Street, |
| 29 | + Line2 = a.Town, |
| 30 | + Line3 = a.City, |
| 31 | + Line4 = a.County, |
| 32 | + Postcode = a.PostalCode |
| 33 | + }); |
| 34 | +``` |
| 35 | + |
| 36 | +## Alternate Data Sources |
| 37 | + |
| 38 | +To map from a data source other than a source model's matching member, an alternate source can be |
| 39 | +configured. Again, this configuration is applied whenever the configured type pair is matched: |
| 40 | + |
| 41 | +```csharp |
| 42 | +Mapper.WhenMapping |
| 43 | + .FromDictionariesWithValueType<ProductDto>() |
| 44 | + .Over<List<Product>>() |
| 45 | + .Map(ctx => ctx.Source.Values) |
| 46 | + .ToTargetInstead(); // <- not ToTarget() |
| 47 | +``` |
| 48 | + |
| 49 | +In this example AgileMapper's usual [Dictionary mapping]({{ site.am_docs }}/Dictionary-Mapping) is |
| 50 | +skipped, and the source Dictionary's `Values` collection is used to update the target `List<Product>` |
| 51 | +using [collection mapping]({{ site.am_docs }}/Collections) instead. |
| 52 | + |
| 53 | +Note that `ToTargetInstead()` is different to `ToTarget()`: |
| 54 | + |
| 55 | +```csharp |
| 56 | +Mapper.WhenMapping |
| 57 | + .FromDictionariesWithValueType<ProductDto>() |
| 58 | + .Over<List<Product>>() |
| 59 | + .Map(ctx => ctx.Source.Values) |
| 60 | + .ToTarget(); // <- not ToTargetInstead() |
| 61 | +``` |
| 62 | + |
| 63 | +With `ToTarget()`, the usual Dictionary mapping is performed, _followed_ by a collection mapping from |
| 64 | +`Dictionary.Values`. |
| 65 | + |
| 66 | +## Sequential Data Sources |
| 67 | + |
| 68 | +A set of data sources can now be applied to a target one after the other: |
| 69 | + |
| 70 | +```csharp |
| 71 | +Mapper.WhenMapping |
| 72 | + .From<Customer>() |
| 73 | + .ToANew<CustomerViewModel>() |
| 74 | + .Map((c, vm) => new[] { c.HomeAddress }) |
| 75 | + .Then.Map((c, vm) => new[] { c.WorkAddress }) |
| 76 | + .Then.Map((c, vm) => c.AddressHistory) |
| 77 | + .To(vm => vm.AllAddresses); |
| 78 | +``` |
| 79 | + |
| 80 | +In this example the target view model's `AllAddresses` collection is populated first using the source |
| 81 | +`Customer`'s `HomeAddress`, then the `WorkAddress`, then the `AddressHistory` collection. Previously |
| 82 | +only one [non-conditional data source]({{ site.am_docs }}/configuration/Member-Values#conditional-data-sources) |
| 83 | +could be configured for a target member - this option enables multiple sources to be applied in sequence. |
| 84 | + |
| 85 | +Please report any issues or suggestions [on GibHub]({{ site.am_github }}/issues). Happy mapping! |
0 commit comments