Skip to content

Commit 7da36f6

Browse files
committed
cosmetic
1 parent 3a491a3 commit 7da36f6

File tree

8 files changed

+52
-56
lines changed

8 files changed

+52
-56
lines changed

src/AutoMapper/ApiCompatBaseline.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ MembersMustExist : Member 'public System.Type System.Type AutoMapper.ValueTransf
4848
InterfacesShouldHaveSameMembers : Default interface member 'public System.Boolean AutoMapper.Configuration.IPropertyMapConfiguration.Ignored' is present in the implementation but not in the contract.
4949
InterfacesShouldHaveSameMembers : Default interface member 'public System.Boolean AutoMapper.Configuration.IPropertyMapConfiguration.Ignored.get()' is present in the implementation but not in the contract.
5050
CannotRemoveBaseTypeOrInterface : Type 'AutoMapper.Configuration.MappingExpression' does not inherit from base type 'AutoMapper.Configuration.MappingExpressionBase' in the implementation but it does in the contract.
51+
TypesMustExist : Type 'AutoMapper.Configuration.MappingExpression.MemberConfigurationExpression' does not exist in the implementation but it does exist in the contract.
5152
CannotRemoveBaseTypeOrInterface : Type 'AutoMapper.Configuration.MappingExpression<TSource, TDestination>' does not inherit from base type 'AutoMapper.Configuration.MappingExpressionBase' in the implementation but it does in the contract.
5253
TypesMustExist : Type 'AutoMapper.Configuration.MappingExpressionBase' does not exist in the implementation but it does exist in the contract.
5354
CannotRemoveBaseTypeOrInterface : Type 'AutoMapper.Configuration.MappingExpressionBase<TSource, TDestination, TMappingExpression>' does not inherit from base type 'AutoMapper.Configuration.MappingExpressionBase' in the implementation but it does in the contract.
@@ -121,4 +122,4 @@ MembersMustExist : Member 'public AutoMapper.Internal.TypePair AutoMapper.Intern
121122
MembersMustExist : Member 'public System.Linq.IQueryable<TDestination> AutoMapper.QueryableExtensions.Extensions.Map<TSource, TDestination>(System.Linq.IQueryable<TSource>, System.Linq.IQueryable<TDestination>, AutoMapper.IConfigurationProvider)' does not exist in the implementation but it does exist in the contract.
122123
MembersMustExist : Member 'public System.Collections.Generic.IReadOnlyCollection<System.Reflection.MemberInfo> AutoMapper.QueryableExtensions.MemberVisitor.MemberPath.get()' does not exist in the implementation but it does exist in the contract.
123124
TypesMustExist : Type 'AutoMapper.QueryableExtensions.Impl.MemberAccessQueryMapperVisitor' does not exist in the implementation but it does exist in the contract.
124-
Total Issues: 122
125+
Total Issues: 123

src/AutoMapper/Configuration/Conventions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
namespace AutoMapper.Configuration.Conventions;
2-
32
public interface ISourceToDestinationNameMapper
43
{
54
MemberInfo GetSourceMember(TypeDetails sourceTypeDetails, Type destType, Type destMemberType, string nameToSearch);

src/AutoMapper/Configuration/MapperConfiguration.cs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class MapperConfiguration : IGlobalConfiguration
4141
private readonly Dictionary<TypePair, TypeMap> _configuredMaps;
4242
private readonly Dictionary<TypePair, TypeMap> _resolvedMaps;
4343
private readonly LockingConcurrentDictionary<TypePair, TypeMap> _runtimeMaps;
44-
private ProjectionBuilder _projectionBuilder;
44+
private LazyValue<ProjectionBuilder> _projectionBuilder;
4545
private readonly LockingConcurrentDictionary<MapRequest, Delegate> _executionPlans;
4646
private readonly ConfigurationValidator _validator;
4747
private readonly Features<IRuntimeFeature> _features = new();
@@ -74,6 +74,7 @@ public MapperConfiguration(MapperConfigurationExpression configurationExpression
7474
_serviceCtor = configuration.ServiceCtor;
7575
_enableNullPropagationForQueryMapping = configuration.EnableNullPropagationForQueryMapping ?? false;
7676
_maxExecutionPlanDepth = configuration.MaxExecutionPlanDepth + 1;
77+
_projectionBuilder = new(CreateProjectionBuilder);
7778
_recursiveQueriesMaxDepth = configuration.RecursiveQueriesMaxDepth;
7879
Configuration = new((IProfileConfiguration)configuration);
7980
int typeMapsCount = Configuration.TypeMapsCount;
@@ -232,18 +233,8 @@ LambdaExpression GenerateObjectMapperExpression(in MapRequest mapRequest, IObjec
232233
return Lambda(fullExpression, source, destination, ContextParameter);
233234
}
234235
}
235-
IProjectionBuilder IGlobalConfiguration.ProjectionBuilder
236-
{
237-
get
238-
{
239-
if (_projectionBuilder == null)
240-
{
241-
CreateProjectionBuilder();
242-
}
243-
return _projectionBuilder;
244-
void CreateProjectionBuilder() => Interlocked.CompareExchange(ref _projectionBuilder, new(this, _validator.Expression.ProjectionMappers.ToArray()), null);
245-
}
246-
}
236+
ProjectionBuilder CreateProjectionBuilder() => new(this, _validator.Expression.ProjectionMappers.ToArray());
237+
IProjectionBuilder IGlobalConfiguration.ProjectionBuilder => _projectionBuilder.Value;
247238
Func<Type, object> IGlobalConfiguration.ServiceCtor => _serviceCtor;
248239
bool IGlobalConfiguration.EnableNullPropagationForQueryMapping => _enableNullPropagationForQueryMapping;
249240
int IGlobalConfiguration.MaxExecutionPlanDepth => _maxExecutionPlanDepth;
@@ -493,7 +484,7 @@ IObjectMapper FindMapper(TypePair types)
493484
void IGlobalConfiguration.AssertConfigurationIsValid(TypeMap typeMap) => _validator.AssertConfigurationIsValid(this, new[] { typeMap });
494485
void IGlobalConfiguration.AssertConfigurationIsValid(string profileName)
495486
{
496-
if (Profiles.All(x => x.Name != profileName))
487+
if (Array.TrueForAll(Profiles, x => x.Name != profileName))
497488
{
498489
throw new ArgumentOutOfRangeException(nameof(profileName), $"Cannot find any profiles with the name '{profileName}'.");
499490
}
@@ -502,4 +493,11 @@ void IGlobalConfiguration.AssertConfigurationIsValid(string profileName)
502493
void IGlobalConfiguration.AssertConfigurationIsValid<TProfile>() => this.Internal().AssertConfigurationIsValid(typeof(TProfile).FullName);
503494
void IGlobalConfiguration.RegisterAsMap(TypeMapConfiguration typeMapConfiguration) =>
504495
_resolvedMaps[typeMapConfiguration.Types] = GetIncludedTypeMap(new(typeMapConfiguration.SourceType, typeMapConfiguration.DestinationTypeOverride));
496+
}
497+
struct LazyValue<T> where T : class
498+
{
499+
readonly Func<T> _factory;
500+
T _value = null;
501+
public T Value => LazyInitializer.EnsureInitialized(ref _value, _factory);
502+
public LazyValue(Func<T> factory) => _factory = factory;
505503
}

src/AutoMapper/Configuration/MappingExpression.cs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,33 +52,6 @@ internal MemberConfigurationExpression ForMember(MemberInfo destinationProperty,
5252
memberOptions(expression);
5353
return expression;
5454
}
55-
public class MemberConfigurationExpression : MemberConfigurationExpression<object, object, object>, IMemberConfigurationExpression
56-
{
57-
public MemberConfigurationExpression(MemberInfo destinationMember, Type sourceType) : base(destinationMember, sourceType){}
58-
public void MapFrom(Type valueResolverType) => MapFromCore(new(valueResolverType, valueResolverType.GetGenericInterface(typeof(IValueResolver<,,>))));
59-
public void MapFrom(Type valueResolverType, string sourceMemberName) =>
60-
MapFromCore(new(valueResolverType, valueResolverType.GetGenericInterface(typeof(IMemberValueResolver<,,,>)))
61-
{
62-
SourceMemberName = sourceMemberName
63-
});
64-
public void MapFrom<TSource, TDestination, TSourceMember, TDestMember>(IMemberValueResolver<TSource, TDestination, TSourceMember, TDestMember> resolver, string sourceMemberName) =>
65-
MapFromCore(new(resolver, typeof(IMemberValueResolver<TSource, TDestination, TSourceMember, TDestMember>))
66-
{
67-
SourceMemberName = sourceMemberName
68-
});
69-
public void ConvertUsing(Type valueConverterType) => ConvertUsingCore(valueConverterType);
70-
public void ConvertUsing(Type valueConverterType, string sourceMemberName) => ConvertUsingCore(valueConverterType, sourceMemberName);
71-
public void ConvertUsing<TSourceMember, TDestinationMember>(IValueConverter<TSourceMember, TDestinationMember> valueConverter, string sourceMemberName) =>
72-
base.ConvertUsingCore(new(valueConverter, typeof(IValueConverter<TSourceMember, TDestinationMember>))
73-
{
74-
SourceMemberName = sourceMemberName
75-
});
76-
private void ConvertUsingCore(Type valueConverterType, string sourceMemberName = null) =>
77-
base.ConvertUsingCore(new(valueConverterType, valueConverterType.GetGenericInterface(typeof(IValueConverter<,>)))
78-
{
79-
SourceMemberName = sourceMemberName
80-
});
81-
}
8255
}
8356
public class MappingExpression<TSource, TDestination> : MappingExpressionBase<TSource, TDestination, IMappingExpression<TSource, TDestination>>,
8457
IMappingExpression<TSource, TDestination>, IProjectionExpression<TSource, TDestination>

src/AutoMapper/Configuration/MemberConfigurationExpression.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,31 @@ public IPropertyMapConfiguration Reverse()
165165
return PathConfigurationExpression<TDestination, TSource, object>.Create(SourceExpression, GetDestinationExpression());
166166
}
167167
public void DoNotUseDestinationValue() => SetUseDestinationValue(false);
168+
}
169+
public class MemberConfigurationExpression : MemberConfigurationExpression<object, object, object>, IMemberConfigurationExpression
170+
{
171+
public MemberConfigurationExpression(MemberInfo destinationMember, Type sourceType) : base(destinationMember, sourceType){}
172+
public void MapFrom(Type valueResolverType) => MapFromCore(new(valueResolverType, valueResolverType.GetGenericInterface(typeof(IValueResolver<,,>))));
173+
public void MapFrom(Type valueResolverType, string sourceMemberName) =>
174+
MapFromCore(new(valueResolverType, valueResolverType.GetGenericInterface(typeof(IMemberValueResolver<,,,>)))
175+
{
176+
SourceMemberName = sourceMemberName
177+
});
178+
public void MapFrom<TSource, TDestination, TSourceMember, TDestMember>(IMemberValueResolver<TSource, TDestination, TSourceMember, TDestMember> resolver, string sourceMemberName) =>
179+
MapFromCore(new(resolver, typeof(IMemberValueResolver<TSource, TDestination, TSourceMember, TDestMember>))
180+
{
181+
SourceMemberName = sourceMemberName
182+
});
183+
public void ConvertUsing(Type valueConverterType) => ConvertUsingCore(valueConverterType);
184+
public void ConvertUsing(Type valueConverterType, string sourceMemberName) => ConvertUsingCore(valueConverterType, sourceMemberName);
185+
public void ConvertUsing<TSourceMember, TDestinationMember>(IValueConverter<TSourceMember, TDestinationMember> valueConverter, string sourceMemberName) =>
186+
base.ConvertUsingCore(new(valueConverter, typeof(IValueConverter<TSourceMember, TDestinationMember>))
187+
{
188+
SourceMemberName = sourceMemberName
189+
});
190+
private void ConvertUsingCore(Type valueConverterType, string sourceMemberName = null) =>
191+
base.ConvertUsingCore(new(valueConverterType, valueConverterType.GetGenericInterface(typeof(IValueConverter<,>)))
192+
{
193+
SourceMemberName = sourceMemberName
194+
});
168195
}

src/AutoMapper/Features.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.Collections;
2-
namespace AutoMapper.Features;
1+
namespace AutoMapper.Features;
32
public interface IGlobalFeature
43
{
54
void Configure(IGlobalConfiguration configuration);

src/AutoMapper/ProfileMap.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class ProfileMap
99
private TypeMapConfiguration[] _typeMapConfigs;
1010
private Dictionary<TypePair, TypeMapConfiguration> _openTypeMapConfigs;
1111
private Dictionary<Type, TypeDetails> _typeDetails;
12-
private ConcurrentDictionary<Type, TypeDetails> _runtimeTypeDetails;
12+
private LazyValue<ConcurrentDictionary<Type, TypeDetails>> _runtimeTypeDetails;
1313
public ProfileMap(IProfileConfiguration profile, IGlobalConfigurationExpression configuration = null)
1414
{
1515
var globalProfile = (IProfileConfiguration)configuration;
@@ -39,6 +39,7 @@ public ProfileMap(IProfileConfiguration profile, IGlobalConfigurationExpression
3939
TypeMapConfigs();
4040
OpenTypeMapConfigs();
4141
_typeDetails = new(2 * _typeMapConfigs.Length);
42+
_runtimeTypeDetails = new(()=>new(Environment.ProcessorCount, 2 * _openTypeMapConfigs.Count));
4243
return;
4344
void TypeMapConfigs()
4445
{
@@ -99,7 +100,7 @@ public TypeDetails CreateTypeDetails(Type type)
99100
{
100101
if (_typeDetails == null)
101102
{
102-
return CreateRuntimeTypeDetails(type);
103+
return _runtimeTypeDetails.Value.GetOrAdd(type, (type, profile) => new(type, profile), this);
103104
}
104105
if (_typeDetails.TryGetValue(type, out var typeDetails))
105106
{
@@ -108,14 +109,6 @@ public TypeDetails CreateTypeDetails(Type type)
108109
typeDetails = new(type, this);
109110
_typeDetails.Add(type, typeDetails);
110111
return typeDetails;
111-
TypeDetails CreateRuntimeTypeDetails(Type type)
112-
{
113-
if (_runtimeTypeDetails == null)
114-
{
115-
Interlocked.CompareExchange(ref _runtimeTypeDetails, new(Environment.ProcessorCount, 2 * _openTypeMapConfigs.Count), null);
116-
}
117-
return _runtimeTypeDetails.GetOrAdd(type, (type, profile) => new(type, profile), this);
118-
}
119112
}
120113
public void Register(IGlobalConfiguration configuration)
121114
{
@@ -187,7 +180,7 @@ private void Configure(TypeMap typeMap, IGlobalConfiguration configuration)
187180
{
188181
foreach (var propertyMap in typeMap.PropertyMaps)
189182
{
190-
var memberExpression = new MappingExpression.MemberConfigurationExpression(propertyMap.DestinationMember, typeMap.SourceType);
183+
var memberExpression = new MemberConfigurationExpression(propertyMap.DestinationMember, typeMap.SourceType);
191184
action(propertyMap, memberExpression);
192185
memberExpression.Configure(typeMap);
193186
}

src/UnitTests/Projection/ProjectTest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ public class FooDto
2020
public void Should_work()
2121
{
2222
new[] { new Foo() }.AsQueryable().ProjectTo<FooDto>(Configuration).Single().A.ShouldBe(0);
23+
24+
var p1 = Configuration.Internal().ProjectionBuilder;
25+
var p2 = Configuration.Internal().ProjectionBuilder;
26+
p2.ShouldBe(p1);
27+
var profile = Configuration.Internal().Profiles[0];
28+
profile.CreateTypeDetails(typeof(DateTime)).ShouldBe(profile.CreateTypeDetails(typeof(DateTime)));
2329
}
2430
}
2531

0 commit comments

Comments
 (0)