static IEnumerable EnumerateMembers()

in src/DurableTask.AzureStorage/Tracking/TableEntityConverter.cs [215:253]


        static IEnumerable<(string Name, Type MemberType, MemberInfo Metadata)> EnumerateMembers(Type type)
        {
            const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;

            // Loop through the type hierarchy to find all [DataMember] attributes which belong to [DataContract] classes.
            while (type != null && type.GetCustomAttribute<DataContractAttribute>() != null)
            {
                foreach (MemberInfo member in type.GetMembers(Flags))
                {
                    DataMemberAttribute dataMember = member.GetCustomAttribute<DataMemberAttribute>();
                    if (dataMember == null)
                    {
                        continue;
                    }

                    PropertyInfo property = member as PropertyInfo;
                    FieldInfo field = member as FieldInfo;
                    if (property == null && field == null)
                    {
                        throw new InvalidDataContractException("Only fields and properties can be marked as [DataMember].");
                    }
                    else if ((property != null && (!property.CanWrite || !property.CanRead)) || (field != null && field.IsInitOnly))
                    {
                        throw new InvalidDataContractException("[DataMember] properties must be both readable and writeable.");
                    }

                    // Timestamp is a reserved property name in Table Storage, so the name needs to be changed.
                    string name = dataMember.Name ?? member.Name;
                    if (string.Equals(name, "Timestamp", StringComparison.OrdinalIgnoreCase))
                    {
                        name = "_Timestamp";
                    }

                    yield return (name, property != null ? property.PropertyType : field.FieldType, member);
                }

                type = type.BaseType;
            }
        }