【问题标题】:Reflection, how to get the PropertyType value and convert to IEnumerable反射,如何获取 PropertyType 值并转换为 IEnumerable
【发布时间】:2019-01-09 14:19:48
【问题描述】:

在我的解决方案中,我有一个业务验证服务,可以应用于任何具有实体类型基类的类。

现在我需要汇总被破坏但卡住的规则,我有可以是集合的属性,所以我还需要检查集合中的每个项目。

为此,我有这张支票

typeof(IEnumerable).IsAssignableFrom(property.PropertyType)

但现在我知道该类型是一个集合。 如何转换为该类型 IEnumerable<T> 以便我可以继续下一步。

这应该将检测到的集合中的项目作为第一个参数。

类似的东西

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

其中collection是转换或强制转换的结果

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 时,你想检查什么?
  • 您是否希望获得property.PropertyType.GetGenericArguments().First()
  • 我不确定我需要做什么。我知道我需要得到什么。作为通用集合存储在属性中的值。所以我想我需要一个 IEnumerable
  • 好吧,property.PropertyType 会给你IEnumerable&lt;Something&gt;,我第一条评论中的代码会给你Something
  • 如果您确定实现了IEnumerable,请尝试强制转换(IEnumerable)propertyValue

标签: c# .net reflection


【解决方案1】:

如果你写出一个描述你想要什么的规范,然后实现处理每个部分的函数,这通常会有所帮助。这可以预先提供更多的清晰度或在现有问题中引入清晰度。例如:

可以检查类型的属性。

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

            // ...
        }
    }    
}

您可能会注意到我们在谈论 instances 而不是 types。由于您对浏览集合感兴趣,您可能并不关心特定 type 的结构是否无效,您可能关心是否已获得特定 instance 要么违反规则,要么包含属性包含违反规则的实例

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    相关资源
    最近更新 更多