/
dev-npgsql
/
npgsql
Обзор
Документация
Войти
/
dev-npgsql
/
npgsql
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
test-logs
src/Npgsql/Internal/DynamicTypeInfoResolver.cs
162 строки
8 KB
Nino Floris
Align missed renames with #6316
20 апр 2026, 19:45
Не верифицирован
20 апр 2026, 19:45
f59c06f
Код
Авторство
О чём код?
using System; using System.Diagnostics.CodeAnalysis; using Npgsql.Internal.Postgres; using Npgsql.PostgresTypes; namespace Npgsql.Internal; [Experimental(NpgsqlDiagnostics.ConvertersExperimental)] [RequiresDynamicCode("A dynamic type info resolver may need to construct a generic converter for a statically unknown type.")] public abstract class DynamicTypeInfoResolver : IPgTypeInfoResolver { public PgTypeInfo? GetTypeInfo(Type? type, DataTypeName? dataTypeName, PgSerializerOptions options) { if (dataTypeName is null) return null; var context = GetMappings(type, dataTypeName.GetValueOrDefault(), options); return context?.Find(type, dataTypeName.GetValueOrDefault(), options); } protected static DynamicMappingCollection CreateCollection(TypeInfoMappingCollection? baseCollection = null) => new(baseCollection); protected static bool IsTypeOrNullableOfType(Type type, Func<Type, bool> predicate, out Type matchedType) { matchedType = Nullable.GetUnderlyingType(type) ?? type; return predicate(matchedType); } protected static bool IsArrayLikeType(Type type, [NotNullWhen(true)]out Type? elementType) => TypeInfoMappingCollection.IsArrayLikeType(type, out elementType); protected static bool IsArrayDataTypeName(DataTypeName dataTypeName, PgSerializerOptions options, out DataTypeName elementDataTypeName) { if (options.DatabaseInfo.GetPostgresType(dataTypeName) is PostgresArrayType arrayType) { elementDataTypeName = arrayType.Element.DataTypeName; return true; } elementDataTypeName = default; return false; } protected abstract DynamicMappingCollection? GetMappings(Type? type, DataTypeName dataTypeName, PgSerializerOptions options); [RequiresDynamicCode("A dynamic type info resolver may need to construct a generic converter for a statically unknown type.")] protected class DynamicMappingCollection { TypeInfoMappingCollection? _mappings; internal DynamicMappingCollection(TypeInfoMappingCollection? baseCollection = null) { if (baseCollection is not null) _mappings = new(baseCollection); } public DynamicMappingCollection AddMapping([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]Type type, string dataTypeName, TypeInfoFactory factory, Func<TypeInfoMapping, TypeInfoMapping>? configureMapping = null) { if (type.IsValueType) { if (Nullable.GetUnderlyingType(type) is not null) throw new NotSupportedException("Mapping nullable types is not supported, map its underlying type instead to get both."); typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddStructType), [typeof(string), typeof(TypeInfoFactory), typeof(Func<TypeInfoMapping, TypeInfoMapping>)])! .MakeGenericMethod(type).Invoke(_mappings ??= new(), [ dataTypeName, factory, configureMapping ]); } else { typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddType), [typeof(string), typeof(TypeInfoFactory), typeof(Func<TypeInfoMapping, TypeInfoMapping>)])! .MakeGenericMethod(type).Invoke(_mappings ??= new(), [ dataTypeName, factory, configureMapping ]); } return this; } public DynamicMappingCollection AddArrayMapping([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]Type elementType, string dataTypeName) { if (elementType.IsValueType) { if (Nullable.GetUnderlyingType(elementType) is not null) throw new NotSupportedException("Mapping nullable types is not supported, map its underlying type instead to get both."); typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddStructArrayType), [typeof(string)])! .MakeGenericMethod(elementType).Invoke(_mappings ??= new(), [dataTypeName]); } else { typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddArrayType), [typeof(string)])! .MakeGenericMethod(elementType).Invoke(_mappings ??= new(), [dataTypeName]); } return this; } public DynamicMappingCollection AddProviderMapping([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]Type type, string dataTypeName, TypeInfoFactory factory, Func<TypeInfoMapping, TypeInfoMapping>? configureMapping = null) { if (type.IsValueType) { if (Nullable.GetUnderlyingType(type) is not null) throw new NotSupportedException("Mapping nullable types is not supported, map its underlying type instead to get both."); typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddProviderStructType), [typeof(string), typeof(TypeInfoFactory), typeof(Func<TypeInfoMapping, TypeInfoMapping>)])! .MakeGenericMethod(type).Invoke(_mappings ??= new(), [ dataTypeName, factory, configureMapping ]); } else { typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddProviderType), [typeof(string), typeof(TypeInfoFactory), typeof(Func<TypeInfoMapping, TypeInfoMapping>)])! .MakeGenericMethod(type).Invoke(_mappings ??= new(), [ dataTypeName, factory, configureMapping ]); } return this; } public DynamicMappingCollection AddProviderArrayMapping([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]Type elementType, string dataTypeName) { if (elementType.IsValueType) { if (Nullable.GetUnderlyingType(elementType) is not null) throw new NotSupportedException("Mapping nullable types is not supported, map its underlying type instead to get both."); typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddProviderStructArrayType), [typeof(string)])! .MakeGenericMethod(elementType).Invoke(_mappings ??= new(), [dataTypeName]); } else { typeof(TypeInfoMappingCollection) .GetMethod(nameof(TypeInfoMappingCollection.AddProviderArrayType), [typeof(string)])! .MakeGenericMethod(elementType).Invoke(_mappings ??= new(), [dataTypeName]); } return this; } internal PgTypeInfo? Find(Type? type, DataTypeName dataTypeName, PgSerializerOptions options) => _mappings?.Find(type, dataTypeName, options); public TypeInfoMappingCollection ToTypeInfoMappingCollection() => new(_mappings?.Items ?? Array.Empty<TypeInfoMapping>()); } }