使用反射的泛型继承问题

发布于 2024-10-19 20:23:59 字数 3142 浏览 1 评论 0原文

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

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() 的函数,该函数使用反射迭代所有属性并检查它们是否更改了它们的值(使用原始属性的副本)商业实体)。它甚至检查该属性本身是否是 Fwk.Business.Entities.BusinessEntity 的实例,如果是,则递归调用 GetChanges 方法。但我的问题是当我有一个属性是 Fwk.Business.Entities.EntityList 的实例时。我想调用每个元素的 GetChanges 方法,但我似乎无法识别这些 EntityList<>特性。 我尝试过使用

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

但是我在执行Ah! 。我认为我的问题是 C# 3.5 不接受协方差(对我来说是新的东西,并且存在于 4.0 中)。因此,我必须将列表公开为 BusinessEntities

At 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;
    }
}

和 at 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);
}

谢谢大家!希望这对将来的人有帮助!

here is my problem:
I am modifying a framework developed in my company, and we have a function that returns any changes in a class' properties.
This is the structure in the framework:

namespace Fwk.Business.Entities

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

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

and this is a tipical use:

namespace Common.Business.Entities
{

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

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

}

Fwk.Business.Entities.BusinessEntity has a function named GetChanges() that using reflection iterates through all properties and checks if they changed their value (using a copy of the original BusinessEntity). It even checks if the property is itself an instance of Fwk.Business.Entities.BusinessEntity and if so recursively calls the GetChanges method. But my problem is when I have a property that is an instance of Fwk.Business.Entities.EntityList. I want to call each element's GetChanges method, but I can't seem to identify these EntityList<> properties.
I've tried with

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

where pi is a PropertyInfo element that identifies the property I'm checking, but this returns false. I've also tried many other Type functions such as IsInstanceOfType and IsAssignableFrom, always getting a false where I need a true.
The weird thing is that if I check for a specific BusinessEntity type it does work:

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

but of course this is not acceptable since I can have a list of ANY BusinessEntity.

Can anyone help me solve this?

Than's in advance for all replys
Alex.

UPDATE:
SLaks gave me a good answer and I coded this:

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

But I'm getting a cast exception when doing

EntityList<BusinessEntity> elList = (EntityList<BusinessEntity>)pi.GetValue(this, null);

Ah! I think my problem is C# 3.5 does not accept covariance (something new to me, and existent in 4.0). So I had to expose a property with the list as BusinessEntities

At EntityList where 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;
    }
}

and at 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);
}

Thanks everyone! Hope this help someone in the future!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

节枝 2024-10-26 20:23:59

您需要递归地循环 Type 的基本类型,并查找 IsGenericTypeGetGenericTypeDefinition() == typeof(EntityList<> 的 Type ;)

You need to recursively loop through the Type's base types, and look for a Type which IsGenericType and for which GetGenericTypeDefinition() == typeof(EntityList<>)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文