diff --git a/Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs b/Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs index 153b6c732..685cadeef 100644 --- a/Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs +++ b/Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs @@ -4,7 +4,6 @@ // Created by: Denis Krjuchkov // Created: 2012.12.29 -using System; using System.Runtime.CompilerServices; using Xtensive.Reflection; @@ -53,79 +52,62 @@ internal static class ValueFieldAccessorResolver private static readonly ValueFieldAccessor GuidAccessor = new GuidFieldAccessor(); private static readonly ValueFieldAccessor DateTimeOffsetAccessor = new DateTimeOffsetFieldAccessor(); - private static readonly ObjectFieldAccessor ObjectAccessor = new ObjectFieldAccessor(); + private static readonly ObjectFieldAccessor ObjectAccessor = new(); - private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken; - - public static ValueFieldAccessor GetValue(Type probeType) + private sealed class TypeReferenceEqualityComparer : IEqualityComparer { - return (probeType.MetadataToken ^ NullableTypeMetadataToken) == 0 - ? (ResolveByNullableType(probeType) ?? TryResolveNullableEnum(probeType)) - : (ResolveByType(probeType) ?? TryResolveEnum(probeType)); + public static readonly TypeReferenceEqualityComparer Instance = new(); + public bool Equals(Type x, Type y) => ReferenceEquals(x, y); + public int GetHashCode(Type obj) => obj.GetHashCode(); } - private static ValueFieldAccessor ResolveByType(Type type) + private static readonly Dictionary TypeToAccessor = new(TypeReferenceEqualityComparer.Instance) { - return ReferenceEquals(type, WellKnownTypes.Int64) ? Int64Accessor : - ReferenceEquals(type, WellKnownTypes.Guid) ? GuidAccessor : - ReferenceEquals(type, WellKnownTypes.Int32) ? Int32Accessor : - ReferenceEquals(type, WellKnownTypes.Bool) ? BoolAccessor : - ReferenceEquals(type, WellKnownTypes.DateTime) ? DateTimeAccessor : - ReferenceEquals(type, WellKnownTypes.TimeSpan) ? TimeSpanAccessor : - ReferenceEquals(type, WellKnownTypes.Double) ? DoubleAccessor : - ReferenceEquals(type, WellKnownTypes.Decimal) ? DecimalAccessor : - ReferenceEquals(type, WellKnownTypes.Single) ? SingleAccessor : - ReferenceEquals(type, WellKnownTypes.DateTimeOffset) ? DateTimeOffsetAccessor : - ReferenceEquals(type, WellKnownTypes.DateOnly) ? DateOnlyAccessor : - ReferenceEquals(type, WellKnownTypes.TimeOnly) ? TimeOnlyAccessor : - ReferenceEquals(type, WellKnownTypes.Int16) ? Int16Accessor : - ReferenceEquals(type, WellKnownTypes.Byte) ? ByteAccessor : - ReferenceEquals(type, WellKnownTypes.SByte) ? SByteAccessor : - ReferenceEquals(type, WellKnownTypes.UInt16) ? UInt16Accessor : - ReferenceEquals(type, WellKnownTypes.UInt32) ? UInt32Accessor : - ReferenceEquals(type, WellKnownTypes.UInt64) ? UInt64Accessor : null; - } + [WellKnownTypes.Int64] = Int64Accessor, + [WellKnownTypes.Guid] = GuidAccessor, + [WellKnownTypes.Int32] = Int32Accessor, + [WellKnownTypes.Bool] = BoolAccessor, + [WellKnownTypes.DateTime] = DateTimeAccessor, + [WellKnownTypes.TimeSpan] = TimeSpanAccessor, + [WellKnownTypes.Double] = DoubleAccessor, + [WellKnownTypes.Decimal] = DecimalAccessor, + [WellKnownTypes.Single] = SingleAccessor, + [WellKnownTypes.DateTimeOffset] = DateTimeOffsetAccessor, + [WellKnownTypes.DateOnly] = DateOnlyAccessor, + [WellKnownTypes.TimeOnly] = TimeOnlyAccessor, + [WellKnownTypes.Int16] = Int16Accessor, + [WellKnownTypes.Byte] = ByteAccessor, + [WellKnownTypes.SByte] = SByteAccessor, + [WellKnownTypes.UInt16] = UInt16Accessor, + [WellKnownTypes.UInt32] = UInt32Accessor, + [WellKnownTypes.UInt64] = UInt64Accessor, + [WellKnownTypes.NullableBool] = BoolAccessor, + [WellKnownTypes.NullableInt32] = Int32Accessor, + [WellKnownTypes.NullableDouble] = DoubleAccessor, + [WellKnownTypes.NullableDecimal] = DecimalAccessor, + [WellKnownTypes.NullableInt64] = Int64Accessor, + [WellKnownTypes.NullableDateTime] = DateTimeAccessor, + [WellKnownTypes.NullableTimeSpan] = TimeSpanAccessor, + [WellKnownTypes.NullableDateTimeOffset] = DateTimeOffsetAccessor, + [WellKnownTypes.NullableSingle] = SingleAccessor, + [WellKnownTypes.NullableDateOnly] = DateOnlyAccessor, + [WellKnownTypes.NullableTimeOnly] = TimeOnlyAccessor, + [WellKnownTypes.NullableGuid] = GuidAccessor, + [WellKnownTypes.NullableInt16] = Int16Accessor, + [WellKnownTypes.NullableByte] = ByteAccessor, + [WellKnownTypes.NullableSByte] = SByteAccessor, + [WellKnownTypes.NullableUInt16] = UInt16Accessor, + [WellKnownTypes.NullableUInt32] = UInt32Accessor, + [WellKnownTypes.NullableUInt64] = UInt64Accessor + }; - private static ValueFieldAccessor ResolveByNullableType(Type type) - { - return ReferenceEquals(type, WellKnownTypes.NullableBool) ? BoolAccessor : - ReferenceEquals(type, WellKnownTypes.NullableInt32) ? Int32Accessor : - ReferenceEquals(type, WellKnownTypes.NullableDouble) ? DoubleAccessor : - ReferenceEquals(type, WellKnownTypes.NullableDecimal) ? DecimalAccessor : - ReferenceEquals(type, WellKnownTypes.NullableInt64) ? Int64Accessor : - ReferenceEquals(type, WellKnownTypes.NullableDateTime) ? DateTimeAccessor : - ReferenceEquals(type, WellKnownTypes.NullableTimeSpan) ? TimeSpanAccessor : - ReferenceEquals(type, WellKnownTypes.NullableDateTimeOffset) ? DateTimeOffsetAccessor : - ReferenceEquals(type, WellKnownTypes.NullableSingle) ? SingleAccessor : - ReferenceEquals(type, WellKnownTypes.NullableDateOnly) ? DateOnlyAccessor : - ReferenceEquals(type, WellKnownTypes.NullableTimeOnly) ? TimeOnlyAccessor : - ReferenceEquals(type, WellKnownTypes.NullableGuid) ? GuidAccessor : - ReferenceEquals(type, WellKnownTypes.NullableInt16) ? Int16Accessor : - ReferenceEquals(type, WellKnownTypes.NullableByte) ? ByteAccessor : - ReferenceEquals(type, WellKnownTypes.NullableSByte) ? SByteAccessor : - ReferenceEquals(type, WellKnownTypes.NullableUInt16) ? UInt16Accessor : - ReferenceEquals(type, WellKnownTypes.NullableUInt32) ? UInt32Accessor : - ReferenceEquals(type, WellKnownTypes.NullableUInt64) ? UInt64Accessor : null; - } - - private static ValueFieldAccessor TryResolveEnum(Type type) - { - if (!type.IsEnum) { - return null; - } - type = Enum.GetUnderlyingType(type); - return ResolveByType(type); - } + private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken; - private static ValueFieldAccessor TryResolveNullableEnum(Type type) - { - var generic = type.GetGenericArguments()[0]; - if (!generic.IsEnum) { - return null; - } - type = Enum.GetUnderlyingType(generic); - return ResolveByType(type); - } + public static ValueFieldAccessor GetValue(Type probeType) => + TypeToAccessor.GetValueOrDefault(probeType) + ?? ((probeType.MetadataToken == NullableTypeMetadataToken ? probeType.GetGenericArguments()[0] : probeType) is { IsEnum: true } enumType + ? TypeToAccessor.GetValueOrDefault(Enum.GetUnderlyingType(enumType)) + : null); } internal delegate void CounterIncrementer(ref Counters counters); @@ -134,14 +116,13 @@ private static ValueFieldAccessor TryResolveNullableEnum(Type type) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ConfigureFieldAccessor(ref PackedFieldDescriptor descriptor, Type fieldType) => - descriptor.AccessorIndex = ((PackedFieldAccessor)ValueFieldAccessorResolver.GetValue(fieldType))?.Index ?? ObjectFieldAccessor.FixedIndex; + descriptor.AccessorIndex = ValueFieldAccessorResolver.GetValue(fieldType)?.Index ?? ObjectFieldAccessor.FixedIndex; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ConfigureLen1(ref Type fieldType, ref PackedFieldDescriptor descriptor, out int valuesLength, out int objectsLength) { - var valueAccessor = ValueFieldAccessorResolver.GetValue(fieldType); - if (valueAccessor != null) { + if (ValueFieldAccessorResolver.GetValue(fieldType) is { } valueAccessor) { descriptor.AccessorIndex = valueAccessor.Index; descriptor.DataPosition = Val064BitCount; @@ -264,4 +245,4 @@ private static void ConfigureFieldPhase1(ref PackedFieldDescriptor descriptor, r descriptor.Index = counters.ObjectCounter++; } } -} \ No newline at end of file +}