Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to AutoMapper 11 #164

Merged
merged 2 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
build:
strategy:
fail-fast: false
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
build:
strategy:
fail-fast: false
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
10 changes: 2 additions & 8 deletions AutoMapper.Collection.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29411.108
# Visual Studio Version 17
VisualStudioVersion = 17.1.32210.238
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{578F2483-CF08-409D-A316-31BCB7C5D9D0}"
ProjectSection(SolutionItems) = preProject
Expand All @@ -20,8 +20,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.Collection", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.Collection.EntityFramework", "src\AutoMapper.Collection.EntityFramework\AutoMapper.Collection.EntityFramework.csproj", "{E0FD41FD-AF5B-4BEC-970F-8412E7B6C914}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.Collection.LinqToSQL", "src\AutoMapper.Collection.LinqToSQL\AutoMapper.Collection.LinqToSQL.csproj", "{A0A023B6-D02A-4CD3-9B3D-3B3022DB001A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.Collection.Tests", "src\AutoMapper.Collection.Tests\AutoMapper.Collection.Tests.csproj", "{2D3D34AD-6A0A-4382-9A2F-894F52D184A7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.Collection.EntityFramework.Tests", "src\AutoMapper.Collection.EntityFramework.Tests\AutoMapper.Collection.EntityFramework.Tests.csproj", "{BDE127AB-AC3F-44DF-BC33-210DAFD12E15}"
Expand All @@ -40,10 +38,6 @@ Global
{E0FD41FD-AF5B-4BEC-970F-8412E7B6C914}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0FD41FD-AF5B-4BEC-970F-8412E7B6C914}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0FD41FD-AF5B-4BEC-970F-8412E7B6C914}.Release|Any CPU.Build.0 = Release|Any CPU
{A0A023B6-D02A-4CD3-9B3D-3B3022DB001A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0A023B6-D02A-4CD3-9B3D-3B3022DB001A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0A023B6-D02A-4CD3-9B3D-3B3022DB001A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0A023B6-D02A-4CD3-9B3D-3B3022DB001A}.Release|Any CPU.Build.0 = Release|Any CPU
{2D3D34AD-6A0A-4382-9A2F-894F52D184A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D3D34AD-6A0A-4382-9A2F-894F52D184A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D3D34AD-6A0A-4382-9A2F-894F52D184A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks>
<TargetFrameworks>net6.0</TargetFrameworks>
<AssemblyName>AutoMapper.Collection.EntityFramework.Tests</AssemblyName>
<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<Description>Collection updating support for EntityFramework with AutoMapper. Extends DBSet&lt;T&gt; with Persist&lt;TDto&gt;().InsertUpdate(dto) and Persist&lt;TDto&gt;().Delete(dto). Will find the matching object and will Insert/Update/Delete.</Description>
<Authors>Tyler Carlson</Authors>
<TargetFrameworks>net461;netstandard2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<AssemblyName>AutoMapper.Collection.EntityFramework</AssemblyName>
<PackageId>AutoMapper.Collection.EntityFramework</PackageId>
<PackageIcon>icon.png</PackageIcon>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net6.0</TargetFrameworks>
<AssemblyName>AutoMapper.Collection.Tests</AssemblyName>
<RootNamespace>AutoMapper.Collection</RootNamespace>
<IsPackable>false</IsPackable>
Expand All @@ -11,11 +11,6 @@
<ProjectReference Include="..\AutoMapper.Collection\AutoMapper.Collection.csproj" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="$(FluentAssertions)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSDKVersion)" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AutoMapper.EquivalencyExpression;
using System.Collections.Generic;
using System.Linq;
using AutoMapper.Internal;
using FluentAssertions;
using Xunit;

Expand All @@ -14,7 +15,7 @@ public abstract class InheritanceWithCollectionTests : MappingTestBase
public void TypeMap_Should_include_base_types()
{
var mapper = CreateMapper(ConfigureMapper);
var typeMap = mapper.ConfigurationProvider.ResolveTypeMap(typeof(MailOrderDomain), typeof(OrderEf));
var typeMap = mapper.ConfigurationProvider.Internal().ResolveTypeMap(typeof(MailOrderDomain), typeof(OrderEf));

var typePairs = new[]{
new TypePair(typeof(OrderDomain), typeof(OrderEf))
Expand All @@ -26,7 +27,7 @@ public void TypeMap_Should_include_base_types()
public void TypeMap_Should_include_derivied_types()
{
var mapper = CreateMapper(ConfigureMapper);
var typeMap = mapper.ConfigurationProvider.ResolveTypeMap(typeof(OrderDomain), typeof(OrderEf));
var typeMap = mapper.ConfigurationProvider.Internal().ResolveTypeMap(typeof(OrderDomain), typeof(OrderEf));

var typePairs = new[]{
new TypePair(typeof(OnlineOrderDomain), typeof(OnlineOrderEf)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,9 @@ public void Parent_Should_Be_Same_As_Root_Object()
cfg =>
{
cfg.AddCollectionMappers();
cfg.CreateMap<ThingWithCollection, ThingWithCollection>();
cfg.CreateMap<ThingWithCollection, ThingWithCollection>().PreserveReferences();
cfg.CreateMap<ThingCollectionItem, ThingCollectionItem>()
.EqualityComparison((src, dst) => src.ID == dst.ID);
.EqualityComparison((src, dst) => src.ID == dst.ID).PreserveReferences();
});

var root = new ThingWithCollection()
Expand Down
5 changes: 2 additions & 3 deletions src/AutoMapper.Collection/AutoMapper.Collection.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
<PropertyGroup>
<Description>Collection Add/Remove/Update support for AutoMapper. AutoMapper.Collection adds EqualityComparison Expressions for TypeMaps to determine if Source and Destination type are equivalent to each other when mapping collections.</Description>
<Authors>Tyler Carlson</Authors>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<AssemblyName>AutoMapper.Collection</AssemblyName>
<PackageId>AutoMapper.Collection</PackageId>
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://github.com/AutoMapper/Automapper.Collection</PackageProjectUrl>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.1' ">$(PackageTargetFallback);portable-net45+win8+dnxcore50;portable-net45+win8</PackageTargetFallback>
<AssemblyOriginatorKeyFile>../Key.snk</AssemblyOriginatorKeyFile>
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand All @@ -25,7 +24,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="[10.0.0, 11.0.0)" />
<PackageReference Include="AutoMapper" Version="[11.0.0, 12.0.0)" />
<PackageReference Include="MinVer" Version="2.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@
using AutoMapper.Collection.Runtime;
using AutoMapper.EquivalencyExpression;
using AutoMapper.Features;
using AutoMapper.Internal;
using AutoMapper.Mappers;

namespace AutoMapper.Collection.Configuration
{
public class GeneratePropertyMapsExpressionFeature : IGlobalFeature
{
private readonly ObjectToEquivalencyExpressionByEquivalencyExistingMapper _mapper;
private readonly List<Func<Func<Type, object>, IGeneratePropertyMaps>> _generators = new List<Func<Func<Type, object>, IGeneratePropertyMaps>>();

public GeneratePropertyMapsExpressionFeature(ObjectToEquivalencyExpressionByEquivalencyExistingMapper mapper)
{
_mapper = mapper;
}

public void Add(Func<Func<Type, object>, IGeneratePropertyMaps> creator)
{
_generators.Add(creator);
}

void IGlobalFeature.Configure(IConfigurationProvider configurationProvider)
void IGlobalFeature.Configure(IGlobalConfiguration configurationProvider)
{
_mapper.Configuration = configurationProvider;
var generators = _generators
.Select(x => x.Invoke(configurationProvider.ServiceCtor))
.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Linq.Expressions;
using AutoMapper.Collection.Configuration;
using AutoMapper.Collection.Runtime;
using AutoMapper.Internal;
using AutoMapper.Internal.Mappers;
using AutoMapper.Mappers;

namespace AutoMapper.EquivalencyExpression
Expand All @@ -11,52 +13,46 @@ public static class EquivalentExpressions
{
public static void AddCollectionMappers(this IMapperConfigurationExpression cfg)
{
cfg.Features.Set(new GeneratePropertyMapsExpressionFeature());
cfg.InsertBefore<ReadOnlyCollectionMapper>(
new ObjectToEquivalencyExpressionByEquivalencyExistingMapper(),
var mapper = new ObjectToEquivalencyExpressionByEquivalencyExistingMapper();
cfg.Internal().Features.Set(new GeneratePropertyMapsExpressionFeature(mapper));
cfg.Internal().InsertBefore<CollectionMapper>(
mapper,
new EquivalentExpressionAddRemoveCollectionMapper());
}

private static void InsertBefore<TObjectMapper>(this IMapperConfigurationExpression cfg, params IConfigurationObjectMapper[] adds)
private static void InsertBefore<TObjectMapper>(this IMapperConfigurationExpression cfg, params IObjectMapper[] adds)
where TObjectMapper : IObjectMapper
{
var mappers = cfg.Mappers;
var mappers = cfg.Internal().Mappers;
var targetMapper = mappers.FirstOrDefault(om => om is TObjectMapper);
var index = targetMapper == null ? 0 : mappers.IndexOf(targetMapper);
foreach (var mapper in adds.Reverse())
{
mappers.Insert(index, mapper);
}

cfg.Advanced.BeforeSeal(c =>
{
foreach (var configurationObjectMapper in adds)
{
configurationObjectMapper.ConfigurationProvider = c;
}
});
}

internal static IEquivalentComparer GetEquivalentExpression(this IConfigurationObjectMapper mapper, Type sourceType, Type destinationType)
internal static IEquivalentComparer GetEquivalentExpression(this IObjectMapper mapper, Type sourceType,
Type destinationType, IConfigurationProvider configuration)
{
var typeMap = mapper.ConfigurationProvider.ResolveTypeMap(sourceType, destinationType);
var typeMap = configuration.Internal().ResolveTypeMap(sourceType, destinationType);
if (typeMap == null)
{
return null;
}

var comparer = GetEquivalentExpression(mapper.ConfigurationProvider, typeMap);
var comparer = GetEquivalentExpression(configuration, typeMap);
if (comparer == null)
{
foreach (var item in typeMap.IncludedBaseTypes)
{
var baseTypeMap = mapper.ConfigurationProvider.ResolveTypeMap(item.SourceType, item.DestinationType);
var baseTypeMap = configuration.Internal().ResolveTypeMap(item.SourceType, item.DestinationType);
if (baseTypeMap == null)
{
continue;
}

comparer = GetEquivalentExpression(mapper.ConfigurationProvider, baseTypeMap);
comparer = GetEquivalentExpression(configuration, baseTypeMap);
if (comparer != null)
{
break;
Expand All @@ -69,7 +65,7 @@ internal static IEquivalentComparer GetEquivalentExpression(this IConfigurationO
internal static IEquivalentComparer GetEquivalentExpression(IConfigurationProvider configurationProvider, TypeMap typeMap)
{
return typeMap.Features.Get<CollectionMappingFeature>()?.EquivalentComparer
?? configurationProvider.Features.Get<GeneratePropertyMapsFeature>().Get(typeMap);
?? configurationProvider.Internal().Features.Get<GeneratePropertyMapsFeature>().Get(typeMap);
}

/// <summary>
Expand All @@ -89,14 +85,14 @@ public static IMappingExpression<TSource, TDestination> EqualityComparison<TSour
public static void SetGeneratePropertyMaps<TGeneratePropertyMaps>(this IMapperConfigurationExpression cfg)
where TGeneratePropertyMaps : IGeneratePropertyMaps
{
(cfg.Features.Get<GeneratePropertyMapsExpressionFeature>()
(cfg.Internal().Features.Get<GeneratePropertyMapsExpressionFeature>()
?? throw new ArgumentException("Invoke the IMapperConfigurationExpression.AddCollectionMappers() before adding IGeneratePropertyMaps."))
.Add(serviceCtor => (IGeneratePropertyMaps)serviceCtor(typeof(TGeneratePropertyMaps)));
}

public static void SetGeneratePropertyMaps(this IMapperConfigurationExpression cfg, IGeneratePropertyMaps generatePropertyMaps)
{
(cfg.Features.Get<GeneratePropertyMapsExpressionFeature>()
(cfg.Internal().Features.Get<GeneratePropertyMapsExpressionFeature>()
?? throw new ArgumentException("Invoke the IMapperConfigurationExpression.AddCollectionMappers() before adding IGeneratePropertyMaps."))
.Add(_ => generatePropertyMaps);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
using System.Reflection;
using AutoMapper.Collection;
using AutoMapper.EquivalencyExpression;
using AutoMapper.Internal;
using AutoMapper.Internal.Mappers;
using static System.Linq.Expressions.Expression;
using static AutoMapper.Execution.ExpressionBuilder;

namespace AutoMapper.Mappers
{
public class EquivalentExpressionAddRemoveCollectionMapper : EnumerableMapperBase, IConfigurationObjectMapper
public class EquivalentExpressionAddRemoveCollectionMapper : IObjectMapper
{
private readonly CollectionMapper _collectionMapper = new CollectionMapper();

public IConfigurationProvider ConfigurationProvider { get; set; }

public static TDestination Map<TSource, TSourceItem, TDestination, TDestinationItem>(TSource source, TDestination destination, ResolutionContext context, IEquivalentComparer equivalentComparer)
where TSource : IEnumerable<TSourceItem>
where TDestination : ICollection<TDestinationItem>
Expand All @@ -31,8 +32,7 @@ public static TDestination Map<TSource, TSourceItem, TDestination, TDestinationI
var sourceHash = equivalentComparer.GetHashCode(x);

var item = default(TDestinationItem);
List<TDestinationItem> itemList;
if (destList.TryGetValue(sourceHash, out itemList))
if (destList.TryGetValue(sourceHash, out var itemList))
{
item = itemList.FirstOrDefault(dest => equivalentComparer.IsEquivalent(x, dest));
if (item != null)
Expand Down Expand Up @@ -66,19 +66,19 @@ public static TDestination Map<TSource, TSourceItem, TDestination, TDestinationI
private static readonly MethodInfo _mapMethodInfo = typeof(EquivalentExpressionAddRemoveCollectionMapper).GetRuntimeMethods().Single(x => x.IsStatic && x.Name == nameof(Map));
private static readonly ConcurrentDictionary<TypePair, IObjectMapper> _objectMapperCache = new ConcurrentDictionary<TypePair, IObjectMapper>();

public override bool IsMatch(TypePair typePair)
public bool IsMatch(TypePair typePair)
{
return typePair.SourceType.IsEnumerableType()
&& typePair.DestinationType.IsCollectionType();
}

public override Expression MapExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, IMemberMap memberMap,
Expression sourceExpression, Expression destExpression, Expression contextExpression)
public Expression MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, MemberMap memberMap,
Expression sourceExpression, Expression destExpression)
{
var sourceType = TypeHelper.GetElementType(sourceExpression.Type);
var destType = TypeHelper.GetElementType(destExpression.Type);

var equivalencyExpression = this.GetEquivalentExpression(sourceType, destType);
var equivalencyExpression = this.GetEquivalentExpression(sourceType, destType, configurationProvider);
if (equivalencyExpression == null)
{
var typePair = new TypePair(sourceExpression.Type, destExpression.Type);
Expand All @@ -95,14 +95,14 @@ public override Expression MapExpression(IConfigurationProvider configurationPro
}
return _collectionMapper;
})
.MapExpression(configurationProvider, profileMap, memberMap, sourceExpression, destExpression, contextExpression);
.MapExpression(configurationProvider, profileMap, memberMap, sourceExpression, destExpression);
}

var method = _mapMethodInfo.MakeGenericMethod(sourceExpression.Type, sourceType, destExpression.Type, destType);
var map = Call(null, method, sourceExpression, destExpression, contextExpression, Constant(equivalencyExpression));
var map = Call(null, method, sourceExpression, destExpression, ContextParameter, Constant(equivalencyExpression));

var notNull = NotEqual(destExpression, Constant(null));
var collectionMapperExpression = _collectionMapper.MapExpression(configurationProvider, profileMap, memberMap, sourceExpression, destExpression, contextExpression);
var collectionMapperExpression = _collectionMapper.MapExpression(configurationProvider, profileMap, memberMap, sourceExpression, destExpression);
return Condition(notNull, map, Convert(collectionMapperExpression, destExpression.Type));
}
}
Expand Down
16 changes: 9 additions & 7 deletions src/AutoMapper.Collection/Mappers/IConfigurationObjectMapper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace AutoMapper.Mappers
{
public interface IConfigurationObjectMapper : IObjectMapper
{
IConfigurationProvider ConfigurationProvider { get; set; }
}
}
//using AutoMapper.Internal.Mappers;

//namespace AutoMapper.Mappers
//{
// public interface IConfigurationObjectMapper : IObjectMapper
// {
// IConfigurationProvider ConfigurationProvider { get; set; }
// }
//}
Loading