Skip to content
This repository was archived by the owner on May 25, 2023. It is now read-only.

Commit 818f78f

Browse files
committed
Updating to AutoMapper 7.0
1 parent 191acb9 commit 818f78f

File tree

10 files changed

+167
-183
lines changed

10 files changed

+167
-183
lines changed

Build.ps1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,21 @@ $versionSuffix = @{ $true = "--version-suffix=$($suffix)"; $false = ""}[$suffix
4545
echo "build: Package version suffix is $suffix"
4646
echo "build: Build version suffix is $buildSuffix"
4747

48-
exec { dotnet restore }
49-
5048
exec { dotnet build -c Release --version-suffix=$buildSuffix -v q /nologo }
5149

5250
foreach ($test in ls test/*.Tests) {
5351
Push-Location $test
5452

5553
echo "build: Testing project in $test"
5654

57-
& dotnet test -c Release
58-
if($LASTEXITCODE -ne 0) { exit 3 }
59-
60-
Pop-Location
55+
try {
56+
& dotnet test -c Release
57+
if($LASTEXITCODE -ne 0) { exit 3 }
58+
} finally {
59+
Pop-Location
60+
}
6161
}
6262

63-
exec { dotnet pack .\src\AutoMapper.Extensions.Microsoft.DependencyInjection -c Release -o ..\..\artifacts --include-symbols --no-build $versionSuffix }
63+
exec { dotnet pack .\src\AutoMapper.Extensions.Microsoft.DependencyInjection -c Release -o ..\..\artifacts --include-symbols --no-build --no-restore $versionSuffix }
6464

6565
Pop-Location

appveyor.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ branches:
55
only:
66
- master
77
image: Visual Studio 2017
8+
## temporary until 2.1 sdk is installed
9+
install:
10+
- ps: $urlCurrent = "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/2.1.300/dotnet-sdk-2.1.300-win-x64.zip"
11+
- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetsdk"
12+
- ps: mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null
13+
- ps: $tempFileCurrent = [System.IO.Path]::GetTempFileName()
14+
- ps: (New-Object System.Net.WebClient).DownloadFile($urlCurrent, $tempFileCurrent)
15+
- ps: Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFileCurrent, $env:DOTNET_INSTALL_DIR)
16+
- ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path"
817
nuget:
918
disable_publish_on_pr: true
1019
build_script:

src/AutoMapper.Extensions.Microsoft.DependencyInjection/AutoMapper.Extensions.Microsoft.DependencyInjection.csproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<Description>AutoMapper extensions for ASP.NET Core</Description>
55
<Copyright>Copyright Jimmy Bogard</Copyright>
6-
<VersionPrefix>3.2.0</VersionPrefix>
6+
<VersionPrefix>4.0.0</VersionPrefix>
77
<Authors>Jimmy Bogard</Authors>
88
<TargetFrameworks>netstandard2.0</TargetFrameworks>
99
<AssemblyName>AutoMapper.Extensions.Microsoft.DependencyInjection</AssemblyName>
@@ -16,8 +16,7 @@
1616

1717
<ItemGroup>
1818
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
19-
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.0.0" />
20-
<PackageReference Include="AutoMapper" Version="6.1.1" />
19+
<PackageReference Include="AutoMapper" Version="7.0.0" />
2120
</ItemGroup>
2221

2322
</Project>
Lines changed: 124 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,129 @@
1-
namespace AutoMapper
2-
{
3-
using System;
4-
using System.Collections.Generic;
5-
using System.Linq;
6-
using System.Reflection;
7-
using Microsoft.Extensions.DependencyInjection;
8-
using Microsoft.Extensions.DependencyModel;
9-
10-
/// <summary>
11-
/// Extensions to scan for AutoMapper classes and register them with the static/singleton Mapper class
12-
/// - Finds <see cref="Profile"/> classes and initializes AutoMapper with them using <see cref="Mapper.Initialize(Action{AutoMapper.IMapperConfigurationExpression})"/>
13-
/// - Scans for <see cref="ITypeConverter{TSource,TDestination}"/>, <see cref="IValueResolver{TSource,TDestination,TDestMember}"/>, <see cref="IMemberValueResolver{TSource,TDestination,TSourceMember,TDestMember}" /> and <see cref="IMappingAction{TSource,TDestination}"/> implementations and registers them as <see cref="ServiceLifetime.Transient"/>
14-
/// - Registers <see cref="Mapper.Configuration"/> as <see cref="ServiceLifetime.Singleton"/>
15-
/// - Registers <see cref="IMapper"/> as <see cref="ServiceLifetime.Scoped"/> with a service factory of the scoped <see cref="IServiceProvider"/>
16-
/// After calling AddAutoMapper you will have the static <see cref="Mapper"/> configuration initialized and you can use Mapper.Map and ProjectTo in your application code.
17-
/// To use instance-based registration instead of the static <see cref="Mapper"/> class, set the <see cref="UseStaticRegistration"/> to false.
18-
/// </summary>
19-
public static class ServiceCollectionExtensions
20-
{
1+
namespace AutoMapper
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Reflection;
7+
using Microsoft.Extensions.DependencyInjection;
8+
9+
/// <summary>
10+
/// Extensions to scan for AutoMapper classes and register them with the static/singleton Mapper class
11+
/// - Finds <see cref="Profile"/> classes and initializes AutoMapper with them using <see cref="Mapper.Initialize(Action{AutoMapper.IMapperConfigurationExpression})"/>
12+
/// - Scans for <see cref="ITypeConverter{TSource,TDestination}"/>, <see cref="IValueResolver{TSource,TDestination,TDestMember}"/>, <see cref="IMemberValueResolver{TSource,TDestination,TSourceMember,TDestMember}" /> and <see cref="IMappingAction{TSource,TDestination}"/> implementations and registers them as <see cref="ServiceLifetime.Transient"/>
13+
/// - Registers <see cref="Mapper.Configuration"/> as <see cref="ServiceLifetime.Singleton"/>
14+
/// - Registers <see cref="IMapper"/> as <see cref="ServiceLifetime.Scoped"/> with a service factory of the scoped <see cref="IServiceProvider"/>
15+
/// After calling AddAutoMapper you will have the static <see cref="Mapper"/> configuration initialized and you can use Mapper.Map and ProjectTo in your application code.
16+
/// To use instance-based registration instead of the static <see cref="Mapper"/> class, set the <see cref="UseStaticRegistration"/> to false.
17+
/// </summary>
18+
public static class ServiceCollectionExtensions
19+
{
2120
/// <summary>
22-
/// Use the static registration method of Mapper.Initialize. Defaults to true.
21+
/// Use the static registration method of Mapper.Initialize. Defaults to true.
2322
/// When false, an instance of a MapperConfiguration object is registered instead.
24-
/// </summary>
25-
public static bool UseStaticRegistration { get; set; } = true;
26-
27-
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
28-
{
29-
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
30-
}
31-
32-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction)
33-
{
34-
return services.AddAutoMapper(additionalInitAction, AppDomain.CurrentDomain.GetAssemblies());
35-
}
36-
37-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, DependencyContext dependencyContext)
38-
{
39-
return services.AddAutoMapper(additionalInitAction, AppDomain.CurrentDomain.GetAssemblies());
40-
}
41-
42-
private static readonly Action<IMapperConfigurationExpression> DefaultConfig = cfg => { };
43-
44-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, params Assembly[] assemblies)
45-
=> AddAutoMapperClasses(services, null, assemblies);
46-
47-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, params Assembly[] assemblies)
48-
=> AddAutoMapperClasses(services, additionalInitAction, assemblies);
49-
50-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Assembly> assemblies)
23+
/// </summary>
24+
public static bool UseStaticRegistration { get; set; } = true;
25+
26+
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
27+
{
28+
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
29+
}
30+
31+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction)
32+
{
33+
return services.AddAutoMapper(additionalInitAction, AppDomain.CurrentDomain.GetAssemblies());
34+
}
35+
36+
private static readonly Action<IMapperConfigurationExpression> DefaultConfig = cfg => { };
37+
38+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, params Assembly[] assemblies)
39+
=> AddAutoMapperClasses(services, null, assemblies);
40+
41+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, params Assembly[] assemblies)
5142
=> AddAutoMapperClasses(services, additionalInitAction, assemblies);
5243

53-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, IEnumerable<Assembly> assemblies)
54-
=> AddAutoMapperClasses(services, null, assemblies);
55-
56-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, params Type[] profileAssemblyMarkerTypes)
57-
{
58-
return AddAutoMapperClasses(services, null, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
59-
}
60-
61-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, params Type[] profileAssemblyMarkerTypes)
62-
{
63-
return AddAutoMapperClasses(services, additionalInitAction, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
64-
}
65-
66-
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Type> profileAssemblyMarkerTypes)
67-
{
68-
return AddAutoMapperClasses(services, additionalInitAction, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
69-
}
70-
71-
72-
private static IServiceCollection AddAutoMapperClasses(IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Assembly> assembliesToScan)
73-
{
74-
additionalInitAction = additionalInitAction ?? DefaultConfig;
75-
assembliesToScan = assembliesToScan as Assembly[] ?? assembliesToScan.ToArray();
76-
77-
var allTypes = assembliesToScan
78-
.Where(a => a.GetName().Name != nameof(AutoMapper))
79-
.SelectMany(a => a.DefinedTypes)
80-
.ToArray();
81-
82-
var profiles = allTypes
83-
.Where(t => typeof(Profile).GetTypeInfo().IsAssignableFrom(t) && !t.IsAbstract)
84-
.ToArray();
85-
86-
87-
void ConfigAction(IMapperConfigurationExpression cfg)
88-
{
89-
additionalInitAction(cfg);
90-
91-
foreach (var profile in profiles.Select(t => t.AsType()))
92-
{
93-
cfg.AddProfile(profile);
94-
}
95-
}
96-
97-
IConfigurationProvider config;
98-
if (UseStaticRegistration)
99-
{
100-
Mapper.Initialize(ConfigAction);
101-
config = Mapper.Configuration;
102-
}
103-
else
104-
{
105-
config = new MapperConfiguration(ConfigAction);
106-
}
107-
108-
var openTypes = new[]
109-
{
110-
typeof(IValueResolver<,,>),
111-
typeof(IMemberValueResolver<,,,>),
112-
typeof(ITypeConverter<,>),
113-
typeof(IMappingAction<,>)
114-
};
115-
foreach (var type in openTypes.SelectMany(openType => allTypes
116-
.Where(t => t.IsClass
117-
&& !t.IsAbstract
118-
&& t.AsType().ImplementsGenericInterface(openType))))
119-
{
120-
services.AddTransient(type.AsType());
121-
}
122-
123-
services.AddSingleton(config);
124-
return services.AddScoped<IMapper>(sp => new Mapper(sp.GetRequiredService<IConfigurationProvider>(), sp.GetService));
125-
}
126-
127-
private static bool ImplementsGenericInterface(this Type type, Type interfaceType)
128-
{
129-
return type.IsGenericType(interfaceType) || type.GetTypeInfo().ImplementedInterfaces.Any(@interface => @interface.IsGenericType(interfaceType));
130-
}
131-
132-
private static bool IsGenericType(this Type type, Type genericType)
133-
=> type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == genericType;
134-
}
44+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Assembly> assemblies)
45+
=> AddAutoMapperClasses(services, additionalInitAction, assemblies);
46+
47+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, IEnumerable<Assembly> assemblies)
48+
=> AddAutoMapperClasses(services, null, assemblies);
49+
50+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, params Type[] profileAssemblyMarkerTypes)
51+
{
52+
return AddAutoMapperClasses(services, null, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
53+
}
54+
55+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, params Type[] profileAssemblyMarkerTypes)
56+
{
57+
return AddAutoMapperClasses(services, additionalInitAction, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
58+
}
59+
60+
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Type> profileAssemblyMarkerTypes)
61+
{
62+
return AddAutoMapperClasses(services, additionalInitAction, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly));
63+
}
64+
65+
66+
private static IServiceCollection AddAutoMapperClasses(IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, IEnumerable<Assembly> assembliesToScan)
67+
{
68+
additionalInitAction = additionalInitAction ?? DefaultConfig;
69+
assembliesToScan = assembliesToScan as Assembly[] ?? assembliesToScan.ToArray();
70+
71+
var allTypes = assembliesToScan
72+
.Where(a => a.GetName().Name != nameof(AutoMapper))
73+
.SelectMany(a => a.DefinedTypes)
74+
.ToArray();
75+
76+
var profiles = allTypes
77+
.Where(t => typeof(Profile).GetTypeInfo().IsAssignableFrom(t) && !t.IsAbstract)
78+
.ToArray();
79+
80+
81+
void ConfigAction(IMapperConfigurationExpression cfg)
82+
{
83+
additionalInitAction(cfg);
84+
85+
foreach (var profile in profiles.Select(t => t.AsType()))
86+
{
87+
cfg.AddProfile(profile);
88+
}
89+
}
90+
91+
IConfigurationProvider config;
92+
if (UseStaticRegistration)
93+
{
94+
Mapper.Initialize(ConfigAction);
95+
config = Mapper.Configuration;
96+
}
97+
else
98+
{
99+
config = new MapperConfiguration(ConfigAction);
100+
}
101+
102+
var openTypes = new[]
103+
{
104+
typeof(IValueResolver<,,>),
105+
typeof(IMemberValueResolver<,,,>),
106+
typeof(ITypeConverter<,>),
107+
typeof(IMappingAction<,>)
108+
};
109+
foreach (var type in openTypes.SelectMany(openType => allTypes
110+
.Where(t => t.IsClass
111+
&& !t.IsAbstract
112+
&& t.AsType().ImplementsGenericInterface(openType))))
113+
{
114+
services.AddTransient(type.AsType());
115+
}
116+
117+
services.AddSingleton(config);
118+
return services.AddScoped<IMapper>(sp => new Mapper(sp.GetRequiredService<IConfigurationProvider>(), sp.GetService));
119+
}
120+
121+
private static bool ImplementsGenericInterface(this Type type, Type interfaceType)
122+
{
123+
return type.IsGenericType(interfaceType) || type.GetTypeInfo().ImplementedInterfaces.Any(@interface => @interface.IsGenericType(interfaceType));
124+
}
125+
126+
private static bool IsGenericType(this Type type, Type genericType)
127+
=> type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == genericType;
128+
}
135129
}

src/TestApp/Program.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Threading.Tasks;
52

63
namespace TestApp
74
{
8-
using System.Reflection;
95
using AutoMapper;
106
using Microsoft.Extensions.DependencyInjection;
11-
using System.Threading;
12-
using System.Threading.Tasks;
137

148
public class Program
159
{
@@ -19,12 +13,24 @@ public static void Main(string[] args)
1913
services.AddTransient<ISomeService>(sp => new FooService(5));
2014
services.AddAutoMapper(typeof(Source));
2115
var provider = services.BuildServiceProvider();
22-
provider.GetService<IMapper>();
23-
24-
foreach (var service in services)
16+
using (var scope = provider.CreateScope())
2517
{
26-
Console.WriteLine(service.ServiceType + " - " + service.ImplementationType);
18+
var mapper = scope.ServiceProvider.GetService<IMapper>();
19+
20+
foreach (var typeMap in mapper.ConfigurationProvider.GetAllTypeMaps())
21+
{
22+
Console.WriteLine($"{typeMap.SourceType.Name} -> {typeMap.DestinationType.Name}");
23+
}
24+
25+
foreach (var service in services)
26+
{
27+
Console.WriteLine(service.ServiceType + " - " + service.ImplementationType);
28+
}
29+
30+
var dest = mapper.Map<Dest2>(new Source2());
31+
Console.WriteLine(dest.ResolvedValue);
2732
}
33+
2834
Console.ReadKey();
2935
}
3036
}

test/AutoMapper.Extensions.Microsoft.DependencyInjection.Tests/AppDomainResolutionTests.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class AppDomainResolutionTests
1414

1515
public AppDomainResolutionTests()
1616
{
17-
ServiceCollectionExtensions.UseStaticRegistration = true;
17+
ServiceCollectionExtensions.UseStaticRegistration = false;
1818
IServiceCollection services = new ServiceCollection();
1919
services.AddAutoMapper();
2020
_provider = services.BuildServiceProvider();
@@ -37,11 +37,5 @@ public void ShouldResolveMapper()
3737
{
3838
_provider.GetService<IMapper>().ShouldNotBeNull();
3939
}
40-
41-
[Fact]
42-
public void ShouldInitializeStatically()
43-
{
44-
_provider.GetService<IConfigurationProvider>().ShouldBeSameAs(Mapper.Configuration);
45-
}
4640
}
4741
}

0 commit comments

Comments
 (0)