private IEnumerable<MemberInfo> GetAllPublicMembers(
Func<PropertyInfo, bool> propertyAvailableFor,
Func<FieldInfo, bool> fieldAvailableFor,
Func<MemberInfo, bool> memberAvailableFor)
{
var typesToScan = new List<Type>();
for (var t = Type; t != null; t = t.BaseType())
typesToScan.Add(t);
if (Type.IsInterface())
typesToScan.AddRange(Type.GetTypeInfo().ImplementedInterfaces);
// Scan all types for public properties and fields
return typesToScan
.Where(x => x != null) // filter out null types (e.g. type.BaseType == null)
.SelectMany(x => x.GetDeclaredMembers()
.Where(mi => mi.DeclaringType != null && mi.DeclaringType == x)
.Where(
m =>
(m is FieldInfo && fieldAvailableFor((FieldInfo) m)) ||
(m is PropertyInfo && propertyAvailableFor((PropertyInfo) m) &&
!((PropertyInfo) m).GetIndexParameters().Any()))
.Where(memberAvailableFor)
);
}