使用反射的泛型继承问题

时间:2011-02-28 15:04:45

标签: .net list generics reflection inheritance

这是我的问题: 我正在修改我公司开发的框架,我们有一个函数可以返回类属性中的任何更改。 这是框架中的结构:

namespace Fwk.Business.Entities

    public class BusinessEntity : IIdentifiable, ICloneableExt
    {
       ...
    }

    public class EntityList<BE> where BE : BusinessEntity, new()
    {
       ...
    }
}

这是一个典型用途:

namespace Common.Business.Entities
{

    public class ImportFileEntity : Fwk.Business.Entities.BusinessEntity
    {
       ...
    }

    public class ImportFileList : Fwk.Business.Entities.EntityList<ImportFileEntity>
    {
    }

}

Fwk.Business.Entities.BusinessEntity有一个名为GetChanges()的函数,它使用反射遍历所有属性并检查它们是否更改了它们的值(使用原始BusinessEntity的副本)。它甚至检查属性本身是否为Fwk.Business.Entities.BusinessEntity的实例,如果是这样,则以递归方式调用GetChanges方法。但我的问题是当我有一个属性是Fwk.Business.Entities.EntityList的实例。我想调用每个元素的GetChanges方法,但我似乎无法识别这些EntityList&lt;&gt;属性。 我试过

pi.GetValue(this, null).GetType().IsSubclassOf(typeof(EntityList<BusinessEntity>))

其中pi是一个PropertyInfo元素,用于标识我正在检查的属性,但是返回false。我还尝试过很多其他类型的函数,比如IsInstanceOfType和IsAssignableFrom,在需要true的地方总是得到一个false。 奇怪的是,如果我检查特定的BusinessEntity类型它确实有效:

pi.GetValue(this, null).GetType().IsSubclassOf(typeof(EntityList<ImportFileEntity>))

但当然这是不可接受的,因为我可以列出任何BusinessEntity。

任何人都可以帮我解决这个问题吗?

提前回复所有回复 亚历克斯。

更新: SLaks给了我一个很好的答案,我编写了这个代码:

bool isEntityList = false;
Type thisType = (pi.GetValue(this, null) ?? new object()).GetType();
while (thisType != typeof(object) && !isEntityList)
    if (thisType.IsGenericType && thisType.GetGenericTypeDefinition() == typeof(EntityList<>))
        isEntityList = true;
    else
        thisType = thisType.BaseType;

// If property is a subclass of EntityList, invoke GetChanges method.
if (isEntityList)
{
    EntityList<BusinessEntity> elList = (EntityList<BusinessEntity>)pi.GetValue(this, null);
    foreach (BusinessEntity beEntity in elList)
        returnValue += beEntity.GetChanges(messageFormat, stopAtFirstDifference);
}

但是我在做

时遇到了强制转换异常
EntityList<BusinessEntity> elList = (EntityList<BusinessEntity>)pi.GetValue(this, null);

啊!我认为我的问题是C#3.5不接受协方差(对我来说是新的,在4.0中存在)。因此,我不得不将列表中的属性公开为BusinessEntities

在EntityList中,BE:BusinessEntity,new()

public virtual List<BusinessEntity> ItemsAsBE
{
    get
    {
        List<BusinessEntity> returnValue = new List<BusinessEntity>(this.Items.Count);
        foreach (BusinessEntity item in this.Items)
            returnValue.Add(item);
        return returnValue;
    }
}

并在BusinessEntity

// If property is a subclass of EntityList, invoke GetChanges method.
if (isEntityList)
{
    foreach (BusinessEntity beEntity in thisType.GetProperty("ItemsAsBE").GetValue(pi.GetValue(this, null), null) as List<BusinessEntity>)
        returnValue += beEntity.GetChanges(messageFormat, stopAtFirstDifference);
}

谢谢大家!希望这有助于将来的某个人!

1 个答案:

答案 0 :(得分:3)

您需要递归循环遍历Type的基本类型,并查找IsGenericType以及GetGenericTypeDefinition() == typeof(EntityList<>)

的类型
相关问题