开发者

Generics inheritance problem using reflection

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 prope开发者_JAVA技巧rty 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!


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜