如何使用反射迭代ICollection类型属性
本文关键字:类型 属性 ICollection 迭代 何使用 反射 | 更新日期: 2023-09-27 18:27:06
标题只涵盖了我努力实现的一小部分,所以请提前告知。我试图构建一种通用的方法,在实体本身更新时正确更新该实体的集合属性。简言之,我想做一些类似于这里解释的方法,但我想走通用的方式。为此,我创建了一个名为EntityCollectionPropertyAttribute
的属性,并标记了我也需要更新。这里有一个例子:
public class Teacher{
public int TeacherId{get;set;}
public string Name{get;set;}
}
public class Student{
public int StudentId{get;set;}
public string Name {get;set;}
[EntityCollectionProperty]
public virtual ICollection<Teacher> Teachers{get;set;}
}
public bool IsPropertyAnEntityCollection(PropertyInfo prop){
return Attribute.IsDefined(prop, typeof(EntityCollectionPropertyAttribute));
}
public void Update<T>(T entity)where T:class{
DbEntityEntry entry = MyDbContext.Entry(entity);
foreach (var prop in entry.Entity.GetType().GetProperties())
{
if(IsPropertyAnEntityCollection(prop)){
//Here's where I get stuck
}
}
}
假设已更新的父实体是"学生"。除了Name(可能还有ID)属性,我还需要更新Teachers。所以在评论区我需要这样的东西:
var updatedTeachers=studentEntity.Teachers.ToList();
但当然是通用的方式。我还必须独立地查看教师DBSet的DbContext内部。所以我也需要这样的东西:
var exisitingTeachers=MyDbContext.Teachers.ToList();
有什么办法吗?
您可以通过在以下方法中传递属性值prop.GetValue(entity)
来调用ToList
方法:
private IList CollectionToList(object value)
{
var collectionType = value.GetType().GenericTypeArguments.First();
var method = typeof(Enumerable).GetMethod("ToList");
var genericMethod = method.MakeGenericMethod(collectionType);
return (IList)genericMethod.Invoke(null, new[] { value });
}
通过这种方式,您将能够在集合中进行迭代。如果属性值的类型为List
或Array
,并且不需要创建新集合,则可以将值强制转换为IList
并在其中迭代。
为了从数据库上下文中获取值,可以使用Set
方法:
var dbset = MyDbContext.Set(prop.PropertyType.GenericTypeArguments.First());
dbset
也可以传递给CollectionToList
方法,但这样您将从表中加载所有表行,这可能会占用大量时间和内存。