我有嵌套列表的实体:
public class Article : MyEntityBase
{
public Article()
{
Tags = new List<Tag>();
}
[MyAttribute]
public string Title { get; set; }
[MyAttribute]
public virtual List<Tag> Tags { get; set; }
}
public class Tag : EntityBase
{
public string Title { get; set; }
}
public abstract class MyEntityBase
{
public Guid Id { get; set; }
}
此外,我还有一个功能,它收集所有[MyAttribute]
标记的属性并对它们执行某些操作:
public function OperateWithAttributes(IEnumerable<PropertyInfo> properties)
{
foreach (var p in properties)
{
if (p.PropertyType == typeof(string))
{
// do something
}
else if (/* there are code that check property type is List<T> */)
{
/* there are code that iterate list */
}
}
}
List<T>
进行比较?EntityBase
?我正在使用.NET 4.5
答案 0 :(得分:4)
如何将属性类型与
List<T>
进行比较?
正确地将某事物识别为列表是......棘手的;特别是如果你想处理所有边缘情况(自定义IList<Foo>
实现,或者子类List<T>
等的类)。很多框架代码检查“实现非泛型IList
,并且有一个非object
索引器”:
static Type GetListType(Type type)
{
if (type == null) return null;
if (!typeof(IList).IsAssignableFrom(type)) return null;
var indexer = type.GetProperty("Item", new[] { typeof(int) });
if (indexer == null || indexer.PropertyType == typeof(object))
return null;
return indexer.PropertyType;
}
如果我知道它继承自
,如何迭代列表EntityBase
?
假设您的意思是项是从EntityBase
继承的,并且您已确定它是一个列表(来自上一个问题),那么最简单的选项是{{1} }和IList
:
foreach
注意:如果您要获取值 ,您也可以撤消此操作并使用var itemType = GetListType(p.PropertyType);
if(itemType != null && itemType.IsSubclassOf(typeof(EntityBase)))
{
var list = (IList) p.GetValue(obj);
foreach(EntityBase item in list)
{
// ...
}
}
测试 前使用is
:
GetListType
答案 1 :(得分:3)
如何将属性类型与List<T>
进行比较:
if (p.PropertyType.IsGenericType &&
p.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
如果我知道[其项目]是从EntityBase继承的话,如何迭代列表:
var listForIteration = (IEnumerable<EntityBase>)list;
foreach (var item in listForIteration)
{
}
List<T>
不是协变的,但是(从.NET 4.0开始)IEnumerable<T>
是。{/ p>
更新:在发表一些评论之后,这里是您没有问过的问题的答案:
如何测试我是否可以将对象枚举为从EntityBase继承的项目序列,如果是,则循环遍历它:
var listForIteration = list as IEnumerable<EntityBase>;
if (listForIteration != null)
{
foreach (var item in listForIteration)
{
}
}
这将(在.NET 4.0或更高版本上)允许您迭代EntityBase(或派生)对象的任何集合,即使集合不是List<>
(除了那些没有实现IEnumerable<T>
的集合。 1}},但这些很少见。)
答案 2 :(得分:1)
你可能想要像
这样的东西Type type = p.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>) &&
typeof(EntityBase).IsAssignableFrom(type.GetGenericArguments()[0]))
{
// iterate list
}
答案 3 :(得分:1)
如果您只想迭代列表,可以使用IEnumerable<out T>
的协方差:
if (typeof(IEnumerable<EntityBase>).IsAssignableFrom(p.PropertyType))
{
var enumerable = (IEnumerable<EntityBase>)p.GetValue(obj);
foreach (var entity in entities)
{
// do something
}
}
答案 4 :(得分:0)
如果我知道它是从EntityBase继承的话,如何迭代列表?
你知道它是EntityBase
类型的子类,所以不是使用泛型,为什么不去寻找一个好的旧超类引用呢?然后,在List<EntityBase>
做得很好的情况下,不需要在这种情况下使用泛型。