Skip to content

Commit db622ef

Browse files
committed
Using hash codes for Members and certain cache key types
1 parent 50d725e commit db622ef

File tree

6 files changed

+42
-45
lines changed

6 files changed

+42
-45
lines changed

AgileMapper/Members/MappingTypes.cs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@ namespace AgileObjects.AgileMapper.Members
66

77
internal class MappingTypes
88
{
9+
private readonly int _hashCode;
10+
911
public MappingTypes(
1012
Type sourceType,
1113
Type targetType,
12-
bool runtimeTypesAreTheSame,
13-
bool isEnumerable)
14+
bool runtimeTypesAreTheSame)
1415
{
1516
SourceType = sourceType;
1617
TargetType = targetType;
1718
RuntimeTypesAreTheSame = runtimeTypesAreTheSame;
18-
IsEnumerable = isEnumerable;
19+
20+
unchecked
21+
{
22+
_hashCode = (sourceType.GetHashCode() * 397) ^ targetType.GetHashCode();
23+
}
1924
}
2025

2126
#region Factory Method
@@ -85,8 +90,7 @@ public static MappingTypes For<TSource, TTarget>(TSource source, TTarget target)
8590
return new MappingTypes(
8691
sourceType,
8792
targetType,
88-
false, // <- runtimeTypesAreTheSame
89-
isEnumerable);
93+
false);
9094
}
9195

9296
#endregion
@@ -99,25 +103,14 @@ public static MappingTypes For<TSource, TTarget>(TSource source, TTarget target)
99103

100104
public bool RuntimeTypesAreTheSame { get; }
101105

102-
public bool IsEnumerable { get; }
103-
104-
public bool Equals(MappingTypes otherTypes)
105-
{
106-
if (otherTypes == this)
107-
{
108-
return true;
109-
}
110-
111-
return (otherTypes.SourceType == SourceType) && (otherTypes.TargetType == TargetType);
112-
}
106+
public bool Equals(MappingTypes otherTypes) => otherTypes._hashCode == _hashCode;
113107

114108
public MappingTypes WithTypes<TNewSource, TNewTarget>()
115109
{
116110
return new MappingTypes(
117111
typeof(TNewSource),
118112
typeof(TNewTarget),
119-
RuntimeTypesAreTheSame,
120-
IsEnumerable);
113+
RuntimeTypesAreTheSame);
121114
}
122115
}
123116

@@ -129,7 +122,6 @@ internal static class MappingTypes<TSource, TTarget>
129122
public static readonly MappingTypes Fixed = new MappingTypes(
130123
typeof(TSource),
131124
typeof(TTarget),
132-
true, // <- runtimeTypesAreTheSame
133-
TypeInfo<TTarget>.IsEnumerable);
125+
true);
134126
}
135127
}

AgileMapper/Members/Member.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
namespace AgileObjects.AgileMapper.Members
22
{
33
using System;
4-
#if NET_STANDARD
5-
using System.Linq;
6-
#endif
74
using System.Linq.Expressions;
85
using System.Reflection;
96
using Dictionaries;
@@ -18,6 +15,7 @@ internal class Member
1815
public const string RootTargetMemberName = "Target";
1916

2017
private readonly Func<Expression, MemberInfo, Expression> _accessFactory;
18+
private readonly int _hashCode;
2119

2220
private Member(
2321
MemberType memberType,
@@ -55,6 +53,13 @@ private Member(
5553
IsWriteable = isWriteable;
5654
IsRoot = isRoot;
5755

56+
_hashCode = declaringType.GetHashCode();
57+
58+
unchecked
59+
{
60+
_hashCode = (_hashCode * 397) ^ name.GetHashCode();
61+
}
62+
5863
JoiningName = (isRoot || this.IsEnumerableElement()) ? name : "." + name;
5964
IsReadable = memberType.IsReadable();
6065
IsEnumerable = type.IsEnumerable();
@@ -231,15 +236,7 @@ private static class TargetMemberCache<T>
231236
public static readonly Member MemberInstance = RootTarget(typeof(T));
232237
}
233238

234-
public bool Equals(Member otherMember)
235-
{
236-
if (ReferenceEquals(otherMember, this))
237-
{
238-
return true;
239-
}
240-
241-
return (otherMember.DeclaringType == DeclaringType) && (otherMember.Name == Name);
242-
}
239+
public bool Equals(Member otherMember) => otherMember._hashCode == _hashCode;
243240

244241
#region ExcludeFromCodeCoverage
245242
#if DEBUG

AgileMapper/Members/TypeKey.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ namespace AgileObjects.AgileMapper.Members
44

55
internal class TypeKey
66
{
7-
private readonly KeyType _keyType;
7+
private readonly int _hashCode;
88

99
private TypeKey(Type type, KeyType keyType, string name = null)
1010
{
1111
Type = type;
1212
Name = name;
13-
_keyType = keyType;
13+
14+
unchecked
15+
{
16+
_hashCode = ((int)keyType * 397) ^ type.GetHashCode();
17+
}
1418
}
1519

1620
public static TypeKey ForSourceMembers(Type type) => new TypeKey(type, KeyType.SourceMembers);
@@ -27,18 +31,16 @@ private TypeKey(Type type, KeyType keyType, string name = null)
2731

2832
public override bool Equals(object obj)
2933
{
30-
var otherKey = (TypeKey)obj;
31-
3234
// ReSharper disable once PossibleNullReferenceException
33-
return (_keyType == otherKey._keyType) && (Type == otherKey.Type);
35+
return obj.GetHashCode() == _hashCode;
3436
}
3537

3638
#region ExcludeFromCodeCoverage
3739
#if DEBUG
3840
[ExcludeFromCodeCoverage]
3941
#endif
4042
#endregion
41-
public override int GetHashCode() => 0;
43+
public override int GetHashCode() => _hashCode;
4244

4345
private enum KeyType { SourceMembers, TargetMembers, TypeId, Parameter }
4446
}

AgileMapper/ObjectPopulation/Enumerables/EnumerableMappingExpressionFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ internal class EnumerableMappingExpressionFactory : MappingExpressionFactoryBase
1010
public static readonly MappingExpressionFactoryBase Instance = new EnumerableMappingExpressionFactory();
1111

1212
public override bool IsFor(IObjectMappingData mappingData)
13-
=> mappingData.MapperKey.MappingTypes.IsEnumerable;
13+
=> mappingData.MapperData.TargetMember.IsEnumerable;
1414

1515
protected override bool TargetCannotBeMapped(IObjectMappingData mappingData, out Expression nullMappingBlock)
1616
{

AgileMapper/ObjectPopulation/SourceMemberTypeDependentKeyBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace AgileObjects.AgileMapper.ObjectPopulation
99
internal abstract class SourceMemberTypeDependentKeyBase
1010
{
1111
private Func<IMappingData, bool> _sourceMemberTypeTester;
12+
private bool _hasTypeTester;
1213

1314
public IObjectMappingData MappingData { get; set; }
1415

@@ -31,9 +32,10 @@ public void AddSourceMemberTypeTesterIfRequired(IObjectMappingData mappingData =
3132
var typeTestLambda = Expression.Lambda<Func<IMappingData, bool>>(typeTest, Parameters.MappingData);
3233

3334
_sourceMemberTypeTester = typeTestLambda.Compile();
35+
_hasTypeTester = true;
3436
}
3537

3638
protected bool SourceHasRequiredTypes(IMappingDataOwner otherKey)
37-
=> (_sourceMemberTypeTester == null) || _sourceMemberTypeTester.Invoke(otherKey.MappingData);
39+
=> !_hasTypeTester || _sourceMemberTypeTester.Invoke(otherKey.MappingData);
3840
}
3941
}

AgileMapper/SourceAndTargetTypesKey.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ namespace AgileObjects.AgileMapper
44

55
internal class SourceAndTargetTypesKey
66
{
7+
private readonly int _hashCode;
8+
79
public SourceAndTargetTypesKey(Type sourceType, Type targetType)
810
{
911
SourceType = sourceType;
1012
TargetType = targetType;
13+
14+
unchecked
15+
{
16+
_hashCode = (sourceType.GetHashCode() * 397) ^ targetType.GetHashCode();
17+
}
1118
}
1219

1320
public Type SourceType { get; }
@@ -16,18 +23,15 @@ public SourceAndTargetTypesKey(Type sourceType, Type targetType)
1623

1724
public override bool Equals(object obj)
1825
{
19-
var otherKey = (SourceAndTargetTypesKey)obj;
20-
2126
// ReSharper disable once PossibleNullReferenceException
22-
return (otherKey.SourceType == SourceType) &&
23-
(otherKey.TargetType == TargetType);
27+
return obj.GetHashCode() == _hashCode;
2428
}
2529

2630
#region ExcludeFromCodeCoverage
2731
#if DEBUG
2832
[ExcludeFromCodeCoverage]
2933
#endif
3034
#endregion
31-
public override int GetHashCode() => 0;
35+
public override int GetHashCode() => _hashCode;
3236
}
3337
}

0 commit comments

Comments
 (0)