繁体   English   中英

反思,如何获取PropertyType值并转换为IEnumerable

[英]Reflection, how to get the PropertyType value and convert to IEnumerable

在我的解决方案中,我有一个业务验证服务,可以将其应用于任何具有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);
        }
}

如果编写出描述所需内容的规范,然后实现处理各个部分的功能,通常会有所帮助。 这可以预先提供更多的清晰度,也可以在现有问题中引入清晰度。 例如:

可以检查类型的属性。

IEnumerable<PropertyInfo> GetInspectableProperties(Type type) => type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

类型可以是实体实例的序列。

bool TypeCanBeEnumeratedAsEntitySequence(Type type) => typeof(IEnumerable<Entity>).IsAssignableFrom(type);

具有Entity sequence属性的实例可能会检索到存在于集合中的实例。

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

            // ...
        }
    }    
}

您可能会注意到,我们在谈论实例而不是类型 由于您对遍历集合感兴趣,因此您可能不在乎某个特定类型的结构是否无效,您可能会在乎是否获得了一个特定的实例 ,该实例违反规则或包含包含实例的属性违反规则。

您可能需要相应地更改聚合方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM