Skip to content

Commit

Permalink
♻️ Nullable and non nullable type mapping registration simplification (
Browse files Browse the repository at this point in the history
…#453)

* ♻️ Extract value-type mapping logic in default TypeMapper to dedicated method

This reinforces the ordering rule in a centralized place and reduces code duplication.

* ♻️ Extract reference-type mapping logic in default TypeMapper to dedicated method

This reinforces the distinction between value and reference types, makes the code more consistent, and prevents misuse of the main mapping method.

* ♻️ Remove unused default argument on 'DefaultODataTypeMapper.BuildTypeMapping'

The argument is now always provided by all consumers.

Co-authored-by: Juliano Goncalves <juliano.goncalves@poatek.com>
  • Loading branch information
julealgon and Juliano Goncalves authored Jan 21, 2022
1 parent dad7c4c commit 75ba93a
Showing 1 changed file with 60 additions and 67 deletions.
127 changes: 60 additions & 67 deletions src/Microsoft.AspNetCore.OData/Edm/DefaultODataTypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,76 +47,53 @@ private static IDictionary<Type, IEdmPrimitiveTypeReference> ClrPrimitiveTypes

static DefaultODataTypeMapper()
{
// Do not change the order for the nullable or non-nullable. Put nullable ahead of non-nullable.
// By design: non-nullable will overwrite the item1.
BuildTypeMapping<string>(EdmPrimitiveTypeKind.String);
BuildTypeMapping<bool?>(EdmPrimitiveTypeKind.Boolean);
BuildTypeMapping<bool>(EdmPrimitiveTypeKind.Boolean);
BuildTypeMapping<byte?>(EdmPrimitiveTypeKind.Byte);
BuildTypeMapping<byte>(EdmPrimitiveTypeKind.Byte);
BuildTypeMapping<decimal?>(EdmPrimitiveTypeKind.Decimal);
BuildTypeMapping<decimal>(EdmPrimitiveTypeKind.Decimal);
BuildTypeMapping<double?>(EdmPrimitiveTypeKind.Double);
BuildTypeMapping<double>(EdmPrimitiveTypeKind.Double);
BuildTypeMapping<Guid?>(EdmPrimitiveTypeKind.Guid);
BuildTypeMapping<Guid>(EdmPrimitiveTypeKind.Guid);
BuildTypeMapping<short?>(EdmPrimitiveTypeKind.Int16);
BuildTypeMapping<short>(EdmPrimitiveTypeKind.Int16);
BuildTypeMapping<int?>(EdmPrimitiveTypeKind.Int32);
BuildTypeMapping<int>(EdmPrimitiveTypeKind.Int32);
BuildTypeMapping<long?>(EdmPrimitiveTypeKind.Int64);
BuildTypeMapping<long>(EdmPrimitiveTypeKind.Int64);
BuildTypeMapping<sbyte?>(EdmPrimitiveTypeKind.SByte);
BuildTypeMapping<sbyte>(EdmPrimitiveTypeKind.SByte);
BuildTypeMapping<float?>(EdmPrimitiveTypeKind.Single);
BuildTypeMapping<float>(EdmPrimitiveTypeKind.Single);
BuildTypeMapping<byte[]>(EdmPrimitiveTypeKind.Binary);
BuildTypeMapping<Stream>(EdmPrimitiveTypeKind.Stream);
BuildTypeMapping<DateTimeOffset?>(EdmPrimitiveTypeKind.DateTimeOffset);
BuildTypeMapping<DateTimeOffset>(EdmPrimitiveTypeKind.DateTimeOffset);
BuildTypeMapping<TimeSpan?>(EdmPrimitiveTypeKind.Duration);
BuildTypeMapping<TimeSpan>(EdmPrimitiveTypeKind.Duration);
BuildTypeMapping<Date?>(EdmPrimitiveTypeKind.Date);
BuildTypeMapping<Date>(EdmPrimitiveTypeKind.Date);
BuildTypeMapping<TimeOfDay?>(EdmPrimitiveTypeKind.TimeOfDay);
BuildTypeMapping<TimeOfDay>(EdmPrimitiveTypeKind.TimeOfDay);

BuildTypeMapping<Geography>(EdmPrimitiveTypeKind.Geography);
BuildTypeMapping<GeographyPoint>(EdmPrimitiveTypeKind.GeographyPoint);
BuildTypeMapping<GeographyLineString>(EdmPrimitiveTypeKind.GeographyLineString);
BuildTypeMapping<GeographyPolygon>(EdmPrimitiveTypeKind.GeographyPolygon);
BuildTypeMapping<GeographyCollection>(EdmPrimitiveTypeKind.GeographyCollection);
BuildTypeMapping<GeographyMultiLineString>(EdmPrimitiveTypeKind.GeographyMultiLineString);
BuildTypeMapping<GeographyMultiPoint>(EdmPrimitiveTypeKind.GeographyMultiPoint);
BuildTypeMapping<GeographyMultiPolygon>(EdmPrimitiveTypeKind.GeographyMultiPolygon);
BuildTypeMapping<Geometry>(EdmPrimitiveTypeKind.Geometry);
BuildTypeMapping<GeometryPoint>(EdmPrimitiveTypeKind.GeometryPoint);
BuildTypeMapping<GeometryLineString>(EdmPrimitiveTypeKind.GeometryLineString);
BuildTypeMapping<GeometryPolygon>(EdmPrimitiveTypeKind.GeometryPolygon);
BuildTypeMapping<GeometryCollection>(EdmPrimitiveTypeKind.GeometryCollection);
BuildTypeMapping<GeometryMultiLineString>(EdmPrimitiveTypeKind.GeometryMultiLineString);
BuildTypeMapping<GeometryMultiPoint>(EdmPrimitiveTypeKind.GeometryMultiPoint);
BuildTypeMapping<GeometryMultiPolygon>(EdmPrimitiveTypeKind.GeometryMultiPolygon);
BuildReferenceTypeMapping<string>(EdmPrimitiveTypeKind.String);
BuildValueTypeMapping<bool>(EdmPrimitiveTypeKind.Boolean);
BuildValueTypeMapping<byte>(EdmPrimitiveTypeKind.Byte);
BuildValueTypeMapping<decimal>(EdmPrimitiveTypeKind.Decimal);
BuildValueTypeMapping<double>(EdmPrimitiveTypeKind.Double);
BuildValueTypeMapping<Guid>(EdmPrimitiveTypeKind.Guid);
BuildValueTypeMapping<short>(EdmPrimitiveTypeKind.Int16);
BuildValueTypeMapping<int>(EdmPrimitiveTypeKind.Int32);
BuildValueTypeMapping<long>(EdmPrimitiveTypeKind.Int64);
BuildValueTypeMapping<sbyte>(EdmPrimitiveTypeKind.SByte);
BuildValueTypeMapping<float>(EdmPrimitiveTypeKind.Single);
BuildReferenceTypeMapping<byte[]>(EdmPrimitiveTypeKind.Binary);
BuildReferenceTypeMapping<Stream>(EdmPrimitiveTypeKind.Stream);
BuildValueTypeMapping<DateTimeOffset>(EdmPrimitiveTypeKind.DateTimeOffset);
BuildValueTypeMapping<TimeSpan>(EdmPrimitiveTypeKind.Duration);
BuildValueTypeMapping<Date>(EdmPrimitiveTypeKind.Date);
BuildValueTypeMapping<TimeOfDay>(EdmPrimitiveTypeKind.TimeOfDay);

BuildReferenceTypeMapping<Geography>(EdmPrimitiveTypeKind.Geography);
BuildReferenceTypeMapping<GeographyPoint>(EdmPrimitiveTypeKind.GeographyPoint);
BuildReferenceTypeMapping<GeographyLineString>(EdmPrimitiveTypeKind.GeographyLineString);
BuildReferenceTypeMapping<GeographyPolygon>(EdmPrimitiveTypeKind.GeographyPolygon);
BuildReferenceTypeMapping<GeographyCollection>(EdmPrimitiveTypeKind.GeographyCollection);
BuildReferenceTypeMapping<GeographyMultiLineString>(EdmPrimitiveTypeKind.GeographyMultiLineString);
BuildReferenceTypeMapping<GeographyMultiPoint>(EdmPrimitiveTypeKind.GeographyMultiPoint);
BuildReferenceTypeMapping<GeographyMultiPolygon>(EdmPrimitiveTypeKind.GeographyMultiPolygon);
BuildReferenceTypeMapping<Geometry>(EdmPrimitiveTypeKind.Geometry);
BuildReferenceTypeMapping<GeometryPoint>(EdmPrimitiveTypeKind.GeometryPoint);
BuildReferenceTypeMapping<GeometryLineString>(EdmPrimitiveTypeKind.GeometryLineString);
BuildReferenceTypeMapping<GeometryPolygon>(EdmPrimitiveTypeKind.GeometryPolygon);
BuildReferenceTypeMapping<GeometryCollection>(EdmPrimitiveTypeKind.GeometryCollection);
BuildReferenceTypeMapping<GeometryMultiLineString>(EdmPrimitiveTypeKind.GeometryMultiLineString);
BuildReferenceTypeMapping<GeometryMultiPoint>(EdmPrimitiveTypeKind.GeometryMultiPoint);
BuildReferenceTypeMapping<GeometryMultiPolygon>(EdmPrimitiveTypeKind.GeometryMultiPolygon);

// non-standard mappings
BuildTypeMapping<XElement>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildTypeMapping<ushort?>(EdmPrimitiveTypeKind.Int32, isStandard: false);
BuildTypeMapping<ushort>(EdmPrimitiveTypeKind.Int32, isStandard: false);
BuildTypeMapping<uint?>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildTypeMapping<uint>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildTypeMapping<ulong?>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildTypeMapping<ulong>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildTypeMapping<char[]>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildTypeMapping<char?>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildTypeMapping<char>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildTypeMapping<DateTime?>(EdmPrimitiveTypeKind.DateTimeOffset, isStandard: false);
BuildTypeMapping<DateTime>(EdmPrimitiveTypeKind.DateTimeOffset, isStandard: false);
BuildReferenceTypeMapping<XElement>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildValueTypeMapping<ushort>(EdmPrimitiveTypeKind.Int32, isStandard: false);
BuildValueTypeMapping<uint>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildValueTypeMapping<ulong>(EdmPrimitiveTypeKind.Int64, isStandard: false);
BuildReferenceTypeMapping<char[]>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildValueTypeMapping<char>(EdmPrimitiveTypeKind.String, isStandard: false);
BuildValueTypeMapping<DateTime>(EdmPrimitiveTypeKind.DateTimeOffset, isStandard: false);

#if NET6_0
BuildTypeMapping<DateOnly?>(EdmPrimitiveTypeKind.Date, isStandard: false);
BuildTypeMapping<DateOnly>(EdmPrimitiveTypeKind.Date, isStandard: false);
BuildTypeMapping<TimeOnly?>(EdmPrimitiveTypeKind.TimeOfDay, isStandard: false);
BuildTypeMapping<TimeOnly>(EdmPrimitiveTypeKind.TimeOfDay, isStandard: false);
BuildValueTypeMapping<DateOnly>(EdmPrimitiveTypeKind.Date, isStandard: false);
BuildValueTypeMapping<TimeOnly>(EdmPrimitiveTypeKind.TimeOfDay, isStandard: false);
#endif
}
#endregion
Expand Down Expand Up @@ -410,7 +387,7 @@ private static Type ExtractGenericInterface(Type queryType, Type interfaceType)
private static IEnumerable<Type> GetMatchingTypes(string edmFullName, IAssemblyResolver assembliesResolver)
=> TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => t.IsPublic && t.EdmFullName() == edmFullName);

private static void BuildTypeMapping<T>(EdmPrimitiveTypeKind primitiveKind, bool isStandard = true)
private static void BuildTypeMapping<T>(EdmPrimitiveTypeKind primitiveKind, bool isStandard)
{
Type type = typeof(T);
bool isNullable = type.IsNullable();
Expand Down Expand Up @@ -441,5 +418,21 @@ private static void BuildTypeMapping<T>(EdmPrimitiveTypeKind primitiveKind, bool
}
}
}

private static void BuildValueTypeMapping<T>(EdmPrimitiveTypeKind primitiveKind, bool isStandard = true)
where T : struct
{
// Do not change the order for the nullable or non-nullable. Put nullable ahead of non-nullable.
// By design: non-nullable will overwrite the item1.

BuildTypeMapping<T?>(primitiveKind, isStandard);
BuildTypeMapping<T>(primitiveKind, isStandard);
}

private static void BuildReferenceTypeMapping<T>(EdmPrimitiveTypeKind primitiveKind, bool isStandard = true)
where T : class
{
BuildTypeMapping<T>(primitiveKind, isStandard);
}
}
}

0 comments on commit 75ba93a

Please sign in to comment.