第一部分直接回答了你的问题——如何让你正在做的事情发挥作用。第二个有望改变问题并使其变得更容易。
我将检查所有这些Valid 属性的部分分离到一个单独的类中,以便我更容易使用。 (如果这仅适用于Foo,那么您将不需要反射。您已经知道Foo 具有哪些属性。
public static class Validations
{
// x is a Foo or any other object that
// has properties of type AnalyzedProperty<T>
public static bool IsValid(object x)
{
var analyzedParameterProperties = x.GetType()
.GetProperties().Where(prop =>
prop.PropertyType.GetGenericTypeDefinition() == typeof(AnalyzedParameter<>));
var isValid = analyzedParameterProperties.All(analyzedParameterProperty =>
GetIsValidValue(x, analyzedParameterProperty));
return isValid;
}
private static bool GetIsValidValue(object x, PropertyInfo analyzedParameterProperty)
{
var analyzedParameter = analyzedParameterProperty.GetValue(x);
if (analyzedParameter == null) return false; // or true?
var analyzedParameterIsValidProperty = analyzedParameter.GetType()
.GetProperty("Valid", typeof(bool));
return (bool)analyzedParameterIsValidProperty.GetValue(analyzedParameter);
}
}
IsValid 方法接受一个对象(如Foo 的实例)并检索类型与开放的泛型类型AnalyzedParameter<> 匹配的所有属性。
混乱的部分是你不能使用开放的泛型类型来读取每个AnalyzedParameter 对象上的Valid 属性。
所以第二种方法——GetIsValidValue
- 获取属性的值 -
AnalyzedParameter 对象
- 查找返回
bool 的Valid 属性
- 读取该属性并返回其值。
如果AnalyzedProperty<T> 实现了一些具有Valid 属性的接口,这会容易得多。在这种情况下,您可以将每个属性值转换为该接口并以这种方式读取属性,而不是使用反射来查找 Valid 属性。
public class AnalyzedParameter<T> : IHasValidation
{
public T Value { get; set; }
public bool Valid { get; set; }
}
public interface IHasValidation
{
public bool Valid { get; set; }
}
现在剩下的代码可以简单一点:
public static bool IsValid(object x)
{
var analyzedParameterProperties = x.GetType()
.GetProperties().Where(prop =>
typeof(IHasValidation).IsAssignableFrom(prop.PropertyType));
var analyzedParameterValues = analyzedParameterProperties.Select(property =>
property.GetValue(x)).Cast<IHasValidation>();
// This assumes that if the property is null, it's not valid.
// You could instead check for value is null or .Valid == true.
var isValid = analyzedParameterValues.All(value => value?.Valid == true);
return isValid;
}