使用反射的泛型继承问题
这是我的问题: 我正在修改我公司开发的一个框架,我们有一个函数可以返回类属性的任何更改。 这是框架中的结构:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要递归地循环
Type
的基本类型,并查找IsGenericType
且GetGenericTypeDefinition() == typeof(EntityList<> 的 Type ;)
You need to recursively loop through the
Type
's base types, and look for a Type whichIsGenericType
and for whichGetGenericTypeDefinition() == typeof(EntityList<>)