Обычно это помогает, если вы пишете спецификацию, которая описывает, что вы хотите, а затем реализует функции, которые обрабатывают каждую часть. Это может обеспечить немного больше ясности заранее или внести ясность в существующую проблему. Например:
Свойства типа могут быть проверены.
IEnumerable<PropertyInfo> GetInspectableProperties(Type type) => type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
Типом может быть последовательность экземпляров сущностей.
bool TypeCanBeEnumeratedAsEntitySequence(Type type) => typeof(IEnumerable<Entity>).IsAssignableFrom(type);
Экземпляр со свойством последовательности сущностей может иметь экземпляры, присутствующие в извлеченной коллекции.
IEnumerable<Entity> GetEntitiesFromProperty(object instance, PropertyInfo property) => (IEnumerable<Entity>)property.GetValue(instance);
Экземпляр может быть оценен для экземпляров, которые нарушили правила.
IEnumerable<BrokenRule> GetBrokenRulesFor(object instance)
{
var type = instance.GetType();
var properties = GetInspectableProperties(type);
foreach (var property in properties)
{
if (TypeCanBeEnumeratedAsEntitySequence(property.PropertyType))
{
var instanceTypesInCollection = GetEntitiesFromProperty(instance, property);
var brokenRulesInCollection = instanceTypesInCollection.Select(x => GetBrokenRulesFor(x)).SelectMany(x => x);
// ...
}
}
}
Вы можете заметить, что мы говорим о экземплярах , а не типах . Из-за вашего интереса к просмотру коллекций, скорее всего, вам все равно, является ли структура определенного типа недействительной, вам, вероятно, важно, получили ли вы конкретный экземпляр который либо нарушает правила, либо содержит свойства , которые содержат экземпляры , нарушающие правила.
Вы можете изменить свой метод агрегации соответствующим образом.