[英]Usercontrol with List<myclass> doesn't recognize public properties in myclass
[英]How to iterate List<T> where T: MyClass
我有嵌套列表的实体:
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
如何比较属性类型与
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
继承的,并且你已经确定它是一个列表(来自上一个问题),那么最简单的选项是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
:
var value = p.GetValue(obj);
Type itemType;
if(value is IList && (itemType = GetListType(p.PropertyType) != null)
&& itemType.IsSubclassOf(typeof(EntityBase)))
{
var list = (IList)value;
foreach(EntityBase item in list)
{
// ...
}
}
如何比较属性类型与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>
是。
更新 :经过一些评论,这里是你没有问过的问题的答案:
如何测试我是否可以将对象枚举为从EntityBase继承的项目序列,如果是,则循环遍历它:
var listForIteration = list as IEnumerable<EntityBase>;
if (listForIteration != null)
{
foreach (var item in listForIteration)
{
}
}
这将(在.NET 4.0或更高版本上)允许您迭代任何EntityBase(或派生)对象的集合,即使该集合不是List<>
(除了那些没有实现IEnumerable<T>
那些,但那些很少见)。
你可能想要这样的东西
Type type = p.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>) &&
typeof(EntityBase).IsAssignableFrom(type.GetGenericArguments()[0]))
{
// iterate list
}
如果您只想迭代列表,可以使用IEnumerable<out T>
的协方差:
if (typeof(IEnumerable<EntityBase>).IsAssignableFrom(p.PropertyType))
{
var enumerable = (IEnumerable<EntityBase>)p.GetValue(obj);
foreach (var entity in entities)
{
// do something
}
}
如果我知道它是从EntityBase继承的,如何迭代列表?
你知道它是EntityBase
类型的子类,所以不是使用泛型,为什么不去寻找一个好的旧超类引用呢? 然后在这种情况下,当List<EntityBase>
良好时,不需要使用泛型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.