Skip to content

Commit 8f93eec

Browse files
authored
Use Dictionary to resolve type accessors (#425)
* Use `Dictionary` to resolve type accessors * Use Dictionary * Refactor * rearrange ObjectFieldAccessor * Simplify * ignore obj.MetadataToken * Simplify * Simplify
1 parent 24b46ad commit 8f93eec

File tree

1 file changed

+52
-71
lines changed

1 file changed

+52
-71
lines changed

Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs

Lines changed: 52 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// Created by: Denis Krjuchkov
55
// Created: 2012.12.29
66

7-
using System;
87
using System.Runtime.CompilerServices;
98
using Xtensive.Reflection;
109

@@ -53,79 +52,62 @@ internal static class ValueFieldAccessorResolver
5352
private static readonly ValueFieldAccessor GuidAccessor = new GuidFieldAccessor();
5453
private static readonly ValueFieldAccessor DateTimeOffsetAccessor = new DateTimeOffsetFieldAccessor();
5554

56-
private static readonly ObjectFieldAccessor ObjectAccessor = new ObjectFieldAccessor();
55+
private static readonly ObjectFieldAccessor ObjectAccessor = new();
5756

58-
private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken;
59-
60-
public static ValueFieldAccessor GetValue(Type probeType)
57+
private sealed class TypeReferenceEqualityComparer : IEqualityComparer<Type>
6158
{
62-
return (probeType.MetadataToken ^ NullableTypeMetadataToken) == 0
63-
? (ResolveByNullableType(probeType) ?? TryResolveNullableEnum(probeType))
64-
: (ResolveByType(probeType) ?? TryResolveEnum(probeType));
59+
public static readonly TypeReferenceEqualityComparer Instance = new();
60+
public bool Equals(Type x, Type y) => ReferenceEquals(x, y);
61+
public int GetHashCode(Type obj) => obj.GetHashCode();
6562
}
6663

67-
private static ValueFieldAccessor ResolveByType(Type type)
64+
private static readonly Dictionary<Type, ValueFieldAccessor> TypeToAccessor = new(TypeReferenceEqualityComparer.Instance)
6865
{
69-
return ReferenceEquals(type, WellKnownTypes.Int64) ? Int64Accessor :
70-
ReferenceEquals(type, WellKnownTypes.Guid) ? GuidAccessor :
71-
ReferenceEquals(type, WellKnownTypes.Int32) ? Int32Accessor :
72-
ReferenceEquals(type, WellKnownTypes.Bool) ? BoolAccessor :
73-
ReferenceEquals(type, WellKnownTypes.DateTime) ? DateTimeAccessor :
74-
ReferenceEquals(type, WellKnownTypes.TimeSpan) ? TimeSpanAccessor :
75-
ReferenceEquals(type, WellKnownTypes.Double) ? DoubleAccessor :
76-
ReferenceEquals(type, WellKnownTypes.Decimal) ? DecimalAccessor :
77-
ReferenceEquals(type, WellKnownTypes.Single) ? SingleAccessor :
78-
ReferenceEquals(type, WellKnownTypes.DateTimeOffset) ? DateTimeOffsetAccessor :
79-
ReferenceEquals(type, WellKnownTypes.DateOnly) ? DateOnlyAccessor :
80-
ReferenceEquals(type, WellKnownTypes.TimeOnly) ? TimeOnlyAccessor :
81-
ReferenceEquals(type, WellKnownTypes.Int16) ? Int16Accessor :
82-
ReferenceEquals(type, WellKnownTypes.Byte) ? ByteAccessor :
83-
ReferenceEquals(type, WellKnownTypes.SByte) ? SByteAccessor :
84-
ReferenceEquals(type, WellKnownTypes.UInt16) ? UInt16Accessor :
85-
ReferenceEquals(type, WellKnownTypes.UInt32) ? UInt32Accessor :
86-
ReferenceEquals(type, WellKnownTypes.UInt64) ? UInt64Accessor : null;
87-
}
66+
[WellKnownTypes.Int64] = Int64Accessor,
67+
[WellKnownTypes.Guid] = GuidAccessor,
68+
[WellKnownTypes.Int32] = Int32Accessor,
69+
[WellKnownTypes.Bool] = BoolAccessor,
70+
[WellKnownTypes.DateTime] = DateTimeAccessor,
71+
[WellKnownTypes.TimeSpan] = TimeSpanAccessor,
72+
[WellKnownTypes.Double] = DoubleAccessor,
73+
[WellKnownTypes.Decimal] = DecimalAccessor,
74+
[WellKnownTypes.Single] = SingleAccessor,
75+
[WellKnownTypes.DateTimeOffset] = DateTimeOffsetAccessor,
76+
[WellKnownTypes.DateOnly] = DateOnlyAccessor,
77+
[WellKnownTypes.TimeOnly] = TimeOnlyAccessor,
78+
[WellKnownTypes.Int16] = Int16Accessor,
79+
[WellKnownTypes.Byte] = ByteAccessor,
80+
[WellKnownTypes.SByte] = SByteAccessor,
81+
[WellKnownTypes.UInt16] = UInt16Accessor,
82+
[WellKnownTypes.UInt32] = UInt32Accessor,
83+
[WellKnownTypes.UInt64] = UInt64Accessor,
84+
[WellKnownTypes.NullableBool] = BoolAccessor,
85+
[WellKnownTypes.NullableInt32] = Int32Accessor,
86+
[WellKnownTypes.NullableDouble] = DoubleAccessor,
87+
[WellKnownTypes.NullableDecimal] = DecimalAccessor,
88+
[WellKnownTypes.NullableInt64] = Int64Accessor,
89+
[WellKnownTypes.NullableDateTime] = DateTimeAccessor,
90+
[WellKnownTypes.NullableTimeSpan] = TimeSpanAccessor,
91+
[WellKnownTypes.NullableDateTimeOffset] = DateTimeOffsetAccessor,
92+
[WellKnownTypes.NullableSingle] = SingleAccessor,
93+
[WellKnownTypes.NullableDateOnly] = DateOnlyAccessor,
94+
[WellKnownTypes.NullableTimeOnly] = TimeOnlyAccessor,
95+
[WellKnownTypes.NullableGuid] = GuidAccessor,
96+
[WellKnownTypes.NullableInt16] = Int16Accessor,
97+
[WellKnownTypes.NullableByte] = ByteAccessor,
98+
[WellKnownTypes.NullableSByte] = SByteAccessor,
99+
[WellKnownTypes.NullableUInt16] = UInt16Accessor,
100+
[WellKnownTypes.NullableUInt32] = UInt32Accessor,
101+
[WellKnownTypes.NullableUInt64] = UInt64Accessor
102+
};
88103

89-
private static ValueFieldAccessor ResolveByNullableType(Type type)
90-
{
91-
return ReferenceEquals(type, WellKnownTypes.NullableBool) ? BoolAccessor :
92-
ReferenceEquals(type, WellKnownTypes.NullableInt32) ? Int32Accessor :
93-
ReferenceEquals(type, WellKnownTypes.NullableDouble) ? DoubleAccessor :
94-
ReferenceEquals(type, WellKnownTypes.NullableDecimal) ? DecimalAccessor :
95-
ReferenceEquals(type, WellKnownTypes.NullableInt64) ? Int64Accessor :
96-
ReferenceEquals(type, WellKnownTypes.NullableDateTime) ? DateTimeAccessor :
97-
ReferenceEquals(type, WellKnownTypes.NullableTimeSpan) ? TimeSpanAccessor :
98-
ReferenceEquals(type, WellKnownTypes.NullableDateTimeOffset) ? DateTimeOffsetAccessor :
99-
ReferenceEquals(type, WellKnownTypes.NullableSingle) ? SingleAccessor :
100-
ReferenceEquals(type, WellKnownTypes.NullableDateOnly) ? DateOnlyAccessor :
101-
ReferenceEquals(type, WellKnownTypes.NullableTimeOnly) ? TimeOnlyAccessor :
102-
ReferenceEquals(type, WellKnownTypes.NullableGuid) ? GuidAccessor :
103-
ReferenceEquals(type, WellKnownTypes.NullableInt16) ? Int16Accessor :
104-
ReferenceEquals(type, WellKnownTypes.NullableByte) ? ByteAccessor :
105-
ReferenceEquals(type, WellKnownTypes.NullableSByte) ? SByteAccessor :
106-
ReferenceEquals(type, WellKnownTypes.NullableUInt16) ? UInt16Accessor :
107-
ReferenceEquals(type, WellKnownTypes.NullableUInt32) ? UInt32Accessor :
108-
ReferenceEquals(type, WellKnownTypes.NullableUInt64) ? UInt64Accessor : null;
109-
}
110-
111-
private static ValueFieldAccessor TryResolveEnum(Type type)
112-
{
113-
if (!type.IsEnum) {
114-
return null;
115-
}
116-
type = Enum.GetUnderlyingType(type);
117-
return ResolveByType(type);
118-
}
104+
private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken;
119105

120-
private static ValueFieldAccessor TryResolveNullableEnum(Type type)
121-
{
122-
var generic = type.GetGenericArguments()[0];
123-
if (!generic.IsEnum) {
124-
return null;
125-
}
126-
type = Enum.GetUnderlyingType(generic);
127-
return ResolveByType(type);
128-
}
106+
public static ValueFieldAccessor GetValue(Type probeType) =>
107+
TypeToAccessor.GetValueOrDefault(probeType)
108+
?? ((probeType.MetadataToken == NullableTypeMetadataToken ? probeType.GetGenericArguments()[0] : probeType) is { IsEnum: true } enumType
109+
? TypeToAccessor.GetValueOrDefault(Enum.GetUnderlyingType(enumType))
110+
: null);
129111
}
130112

131113
internal delegate void CounterIncrementer(ref Counters counters);
@@ -134,14 +116,13 @@ private static ValueFieldAccessor TryResolveNullableEnum(Type type)
134116

135117
[MethodImpl(MethodImplOptions.AggressiveInlining)]
136118
public static void ConfigureFieldAccessor(ref PackedFieldDescriptor descriptor, Type fieldType) =>
137-
descriptor.AccessorIndex = ((PackedFieldAccessor)ValueFieldAccessorResolver.GetValue(fieldType))?.Index ?? ObjectFieldAccessor.FixedIndex;
119+
descriptor.AccessorIndex = ValueFieldAccessorResolver.GetValue(fieldType)?.Index ?? ObjectFieldAccessor.FixedIndex;
138120

139121
[MethodImpl(MethodImplOptions.AggressiveInlining)]
140122
public static void ConfigureLen1(ref Type fieldType, ref PackedFieldDescriptor descriptor, out int valuesLength,
141123
out int objectsLength)
142124
{
143-
var valueAccessor = ValueFieldAccessorResolver.GetValue(fieldType);
144-
if (valueAccessor != null) {
125+
if (ValueFieldAccessorResolver.GetValue(fieldType) is { } valueAccessor) {
145126
descriptor.AccessorIndex = valueAccessor.Index;
146127
descriptor.DataPosition = Val064BitCount;
147128

@@ -264,4 +245,4 @@ private static void ConfigureFieldPhase1(ref PackedFieldDescriptor descriptor, r
264245
descriptor.Index = counters.ObjectCounter++;
265246
}
266247
}
267-
}
248+
}

0 commit comments

Comments
 (0)