如何使用反射迭代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();

有什么办法吗?

如何使用反射迭代ICollection类型属性

您可以通过在以下方法中传递属性值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 });
}

通过这种方式,您将能够在集合中进行迭代。如果属性值的类型为ListArray,并且不需要创建新集合,则可以将值强制转换为IList并在其中迭代。

为了从数据库上下文中获取值,可以使用Set方法:

var dbset = MyDbContext.Set(prop.PropertyType.GenericTypeArguments.First());

dbset也可以传递给CollectionToList方法,但这样您将从表中加载所有表行,这可能会占用大量时间和内存。