Отражение, как получить значение PropertyType и преобразовать в IEnumerable - PullRequest
0 голосов
/ 09 января 2019

В моем решении у меня есть служба проверки бизнеса, которую можно применить к любому классу с базовым классом типа Entity.

Теперь мне нужно объединить правила, которые нарушены, но застряли, у меня есть свойства, которые могут быть коллекциями, поэтому мне нужно также проверить каждый элемент в коллекции.

Для этого у меня есть этот чек

typeof(IEnumerable).IsAssignableFrom(property.PropertyType)

но теперь, когда я знаю, что тип это коллекция. Как мне привести этот тип IEnumerable<T>, чтобы я мог перейти к следующему шагу.

В качестве первого параметра должен использоваться элемент из обнаруженной коллекции.

как то так

foreach(var collectionItem in collection)
{
      AggregateBrokenRules(collectionItem, ref rules);
}

Где коллекция - результат преобразования или приведения

private void AggregateBrokenRules(Type reflectedType, ref List<BrokenRule> rules)
{
      /// => don't apply any filter of any kind except for what already is provided 
      PropertyInfo[] properties = reflectedType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

      /// => iterate through discovered properties
      foreach (PropertyInfo property in properties)
      {
         /// => if type is IEnumerable
         if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
         {
             /// => cast to IEnumerable 
             var propertyVal = Convert.ChangeType(types, property.PropertyType);


             AggregateBrokenRules(property.PropertyType, ref rules);
          }

          /// => only properties that are of type Entity
          if (typeof(Entity).GetTypeInfo().IsAssignableFrom(property.PropertyType))
          {
              /// => check next level
              AggregateBrokenRules(property.PropertyType, ref rules);
          }

           /// => get the value from this property
           object propertyValue = property.GetValue(reflectedType);
        }
}

1 Ответ

0 голосов
/ 09 января 2019

Обычно это помогает, если вы пишете спецификацию, которая описывает, что вы хотите, а затем реализует функции, которые обрабатывают каждую часть. Это может обеспечить немного больше ясности заранее или внести ясность в существующую проблему. Например:

Свойства типа могут быть проверены.

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

            // ...
        }
    }    
}

Вы можете заметить, что мы говорим о экземплярах , а не типах . Из-за вашего интереса к просмотру коллекций, скорее всего, вам все равно, является ли структура определенного типа недействительной, вам, вероятно, важно, получили ли вы конкретный экземпляр который либо нарушает правила, либо содержит свойства , которые содержат экземпляры , нарушающие правила.

Вы можете изменить свой метод агрегации соответствующим образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...