| | | 1 | | using System.Reflection; |
| | | 2 | | using TeleFlow.Annotations; |
| | | 3 | | using TeleFlow.Framework.States; |
| | | 4 | | |
| | | 5 | | namespace TeleFlow.Telegram.Internal.Handlers; |
| | | 6 | | |
| | | 7 | | internal static class TelegramStateAttributeResolver |
| | | 8 | | { |
| | | 9 | | public static IReadOnlyList<string> GetStates(MemberInfo handlerType, MethodInfo method) |
| | | 10 | | { |
| | 324 | 11 | | return GetStateAttributes(handlerType) |
| | 324 | 12 | | .Concat(GetStateAttributes(method)) |
| | 324 | 13 | | .Select(ResolveState) |
| | 324 | 14 | | .ToArray(); |
| | | 15 | | } |
| | | 16 | | |
| | | 17 | | private static IEnumerable<Attribute> GetStateAttributes(MemberInfo member) |
| | | 18 | | { |
| | 648 | 19 | | return member |
| | 648 | 20 | | .GetCustomAttributes(inherit: true) |
| | 648 | 21 | | .OfType<Attribute>() |
| | 648 | 22 | | .Where(static attribute => |
| | 1497 | 23 | | attribute is StateAttribute || |
| | 1497 | 24 | | IsGenericStateAttribute(attribute.GetType())); |
| | | 25 | | } |
| | | 26 | | |
| | | 27 | | private static string ResolveState(Attribute attribute) |
| | | 28 | | { |
| | 8 | 29 | | if (attribute is StateAttribute stateAttribute) |
| | | 30 | | { |
| | 5 | 31 | | return stateAttribute.State; |
| | | 32 | | } |
| | | 33 | | |
| | 3 | 34 | | var attributeType = attribute.GetType(); |
| | 3 | 35 | | if (!IsGenericStateAttribute(attributeType)) |
| | | 36 | | { |
| | 0 | 37 | | throw new InvalidOperationException( |
| | 0 | 38 | | $"Unsupported Telegram state attribute '{attributeType.FullName}'."); |
| | | 39 | | } |
| | | 40 | | |
| | 3 | 41 | | var stateName = attributeType |
| | 3 | 42 | | .GetProperty(nameof(StateAttribute<object>.StateName))! |
| | 3 | 43 | | .GetValue(attribute) as string; |
| | | 44 | | |
| | 3 | 45 | | if (string.IsNullOrWhiteSpace(stateName)) |
| | | 46 | | { |
| | 0 | 47 | | throw new InvalidOperationException( |
| | 0 | 48 | | $"Typed Telegram state attribute '{attributeType.FullName}' must declare a state member name."); |
| | | 49 | | } |
| | | 50 | | |
| | 3 | 51 | | var groupType = attributeType.GetGenericArguments()[0]; |
| | 3 | 52 | | var property = groupType.GetProperty( |
| | 3 | 53 | | stateName, |
| | 3 | 54 | | BindingFlags.Public | BindingFlags.Static); |
| | | 55 | | |
| | 3 | 56 | | if (property is null || property.PropertyType != typeof(State)) |
| | | 57 | | { |
| | 0 | 58 | | throw new InvalidOperationException( |
| | 0 | 59 | | $"Typed Telegram state attribute references missing state '{groupType.FullName}.{stateName}'."); |
| | | 60 | | } |
| | | 61 | | |
| | 3 | 62 | | return ((State)property.GetValue(null)!).Id; |
| | | 63 | | } |
| | | 64 | | |
| | | 65 | | private static bool IsGenericStateAttribute(Type attributeType) |
| | | 66 | | { |
| | 847 | 67 | | return attributeType.IsGenericType && |
| | 847 | 68 | | attributeType.GetGenericTypeDefinition() == typeof(StateAttribute<>); |
| | | 69 | | } |
| | | 70 | | } |