在我的解决方案中,我有一个业务验证服务,该服务可以应用于实体类型为基类的任何类。
现在,我需要汇总已打破但被卡住的规则,我具有可以作为集合的属性,因此我还需要检查集合中的每个项目。
为此,我要进行此检查
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);
}
}
答案 0 :(得分:1)
通常,如果您写出描述所需内容的规范,然后实现处理各个部分的功能,通常会有所帮助。这可以预先提供更多的清晰度,也可以在现有问题中引入清晰度。例如:
可以检查类型的属性。
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);
// ...
}
}
}
您可能会注意到,我们在谈论的是实例,而不是类型。由于您对遍历集合感兴趣,因此您可能不在意特定 type 的结构是否无效,您可能会在意是否已获得特定的 instance < / em>违反规则或包含属性包含违反规则的实例。
您可能需要相应地更改汇总方法。