< Summary

Information
Class: TeleFlow.Telegram.Internal.TelegramRequestPropertyMetadata
Assembly: TeleFlow.Telegram.Client
File(s): /_/src/TeleFlow.Telegram.Client/Internal/TelegramRequestTypeMetadata.cs
Line coverage
100%
Covered lines: 6
Uncovered lines: 0
Coverable lines: 6
Total lines: 91
Line coverage: 100%
Branch coverage
25%
Covered branches: 1
Total branches: 4
Branch coverage: 25%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_PropertyType()100%11100%
get_Name()100%11100%
get_TelegramName()25%44100%
GetValue(...)100%11100%

File(s)

/_/src/TeleFlow.Telegram.Client/Internal/TelegramRequestTypeMetadata.cs

#LineLine coverage
 1using System.Collections.Concurrent;
 2using System.Reflection;
 3using System.Text.Json.Serialization;
 4
 5namespace TeleFlow.Telegram.Internal;
 6
 7/// <summary>
 8/// Caches reflection metadata used by Telegram request content building.
 9/// The cache keeps JSON property discovery, ignored-property handling, and scalar detection in one place.
 10/// It is shared by JSON/multipart routing and multipart rendering so both paths interpret generated schema types consis
 11/// </summary>
 12internal static class TelegramRequestTypeMetadataCache
 13{
 14    private static readonly ConcurrentDictionary<Type, TelegramRequestTypeMetadata> MetadataCache = new();
 15
 16    public static TelegramRequestTypeMetadata Get(Type type)
 17    {
 18        ArgumentNullException.ThrowIfNull(type);
 19        return MetadataCache.GetOrAdd(type, Create);
 20    }
 21
 22    public static bool IsScalarType(Type type)
 23    {
 24        ArgumentNullException.ThrowIfNull(type);
 25
 26        var scalarType = Nullable.GetUnderlyingType(type) ?? type;
 27
 28        return scalarType.IsPrimitive ||
 29               scalarType.IsEnum ||
 30               scalarType == typeof(string) ||
 31               scalarType == typeof(decimal) ||
 32               scalarType == typeof(DateTime) ||
 33               scalarType == typeof(DateTimeOffset) ||
 34               scalarType == typeof(Guid);
 35    }
 36
 37    private static TelegramRequestTypeMetadata Create(Type type)
 38    {
 39        var readableProperties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
 40            .Where(static property => property.CanRead && property.GetIndexParameters().Length == 0)
 41            // Keep reflection metadata aligned with System.Text.Json and avoid evaluating ignored getters
 42            // while deciding whether a request needs multipart.
 43            .Where(static property => !IsAlwaysJsonIgnored(property))
 44            .Select(static property => new TelegramRequestPropertyMetadata(
 45                property,
 46                property.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name))
 47            .ToArray();
 48
 49        var telegramProperties = readableProperties
 50            .Where(static property => property.JsonPropertyName is not null)
 51            .ToArray();
 52
 53        return new TelegramRequestTypeMetadata(IsScalarType(type), readableProperties, telegramProperties);
 54    }
 55
 56    private static bool IsAlwaysJsonIgnored(PropertyInfo property)
 57    {
 58        var ignore = property.GetCustomAttribute<JsonIgnoreAttribute>();
 59        return ignore?.Condition == JsonIgnoreCondition.Always;
 60    }
 61}
 62
 63/// <summary>
 64/// Reflection snapshot for one request-related CLR type.
 65/// It separates all readable properties from Telegram JSON fields discovered through JsonPropertyName metadata.
 66/// </summary>
 67internal sealed record TelegramRequestTypeMetadata(
 68    bool IsScalar,
 69    TelegramRequestPropertyMetadata[] ReadableProperties,
 70    TelegramRequestPropertyMetadata[] TelegramProperties);
 71
 72/// <summary>
 73/// Reflection wrapper around a readable CLR property and its optional Telegram JSON field name.
 74/// Multipart rendering uses it to read CLR values and write Telegram field names without repeating reflection rules.
 75/// </summary>
 76internal sealed record TelegramRequestPropertyMetadata(PropertyInfo Property, string? JsonPropertyName)
 77{
 25478    public Type PropertyType => Property.PropertyType;
 79
 6980    public string Name => Property.Name;
 81
 82    public string TelegramName =>
 2783        JsonPropertyName ??
 2784        throw new InvalidOperationException(
 2785            $"Telegram payload property '{Property.DeclaringType?.FullName}.{Property.Name}' is missing JsonPropertyName
 86
 87    public object? GetValue(object value)
 88    {
 32689        return Property.GetValue(value);
 90    }
 91}