我有以下课程:

public class BaseDataEntity
{
    private List<string> _Changes = new List<string>();

    public IEnumerable<string> GetChanges()
    {
        return _Changes;
    }

    public bool HasDataChanged
    {
        get { return (GetChanges().Count() > 0); }
    }

    public bool HasChildRecords
    {
        get { return (GetType().GetChildRecords().Count() > 0); }
    }
}

public class ChildRecords : IList<T> where T : BaseDataEntity
{

}


还有一些辅助方法:

public static PropertyInfo[] GetChildRecords(this Type aType)
{
    return aType.GetProperties().Where(pi => pi.IsChildRecords()).ToArray();
}

public static bool IsChildRecords(this PropertyInfo info)
{
    return (info.GetCustomAttributes(typeof(ChildRecordsAttribute), false).Length > 0);
}


我想做的是使用反射实现一个名为HaveChildRecordsChanged的属性。我的问题是我将如何使用反射来检查任意深度的所有ChildRecords的HasDataChanged属性?

我尝试了类似的东西:

var isChanged = false;

foreach (var info in GetType().GetChildRecords())
{
    var childRecordObject = info.GetValue(this, null);
    var childRecords = childRecordObject as ChildRecords<BaseDataEntity>;   //cannot unbox this, it evaluates as null
    if (null != childRecords && childRecords.Any(x => x.HasDataChanged))
    {
        isChanged = true;   //never hit
    }
}

return isChanged;

最佳答案

ChildRecords<T>是通用的,因此不能将ChildRecords<Company>强制转换为ChildRecords<BaseDataEntity>

由于您已经过滤了标记为ChildRecordsAttribute的属性,因此最简单的解决方案是将其强制转换为IEnumerable并使用OfType<BaseDataEntity>()

var childRecords = childRecordObject as IEnumerable; // IList<T> will be IEnumerable
if (null != childRecords && childRecords.OfType<BaseDataEntity>().Any(x => x.HasDataChanged))
{
    isChanged = true;
}

09-08 07:22