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;
}
}