简体   繁体   English

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

[英]How to iterate through an ICollection type property with reflection

The title covers a very tiny part of what I'm trying to achieve, so be informed ahead. 标题仅涵盖了我要实现的目标中很小的一部分,因此请提前告知。 I'm trying to build a generic way of properly updating collection properties of an entity when that entity itself is updated. 我正在尝试建立一种在实体本身更新时正确更新其集合属性的通用方法。 In the nutshell I want to do something similar to the approach explained here but I want to go generic way. 简而言之,我想做一些与这里说明的方法类似的事情,但我想采用通用的方法。 For that I have created an attribute called EntityCollectionPropertyAttribute and marked those properties of entities that I need to be updated too. 为此,我创建了一个名为EntityCollectionPropertyAttribute的属性,并标记了我也需要更新的实体的那些属性。 Here's an example: 这是一个例子:

   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
        }
    }
 }

Lets say the parent entity that has been updated is a Student. 假设已更新的父实体是学生。 Besides Name (and possibly ID) properties, I need the Teachers to be updated as well. 除了名称(可能还有ID)属性外,我还需要更新教师。 So in the commented area I need something like this: 因此,在评论区域中,我需要这样的东西:

 var updatedTeachers=studentEntity.Teachers.ToList();

but of course generic way. 但当然是通用方式。 I will also have to look inside the DbContext for the teachers DBSet independently. 我还必须单独在DbContext内部查找教师DBSet。 So I will need something like this too: 所以我也需要这样的东西:

var exisitingTeachers=MyDbContext.Teachers.ToList();

Any ideas how to do this? 任何想法如何做到这一点?

You can call ToList method by passing property value prop.GetValue(entity) in this method: 您可以通过在此方法中传递属性值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 });
}

In this way you will be able to iterate through collection. 这样,您就可以遍历集合。 If type of property value List or Array and there is no need in creating new collection you can just cast value to IList and iterate through it. 如果属性的类型为ListArray并且不需要创建新的集合,则可以将值IListIList并对其进行迭代。

For getting values from database context you can use Set method: 为了从数据库上下文中获取值,可以使用Set方法:

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

dbset also could be passed to CollectionToList method, but in that way you will load all table rows from table which could take a lot of time and memory. dbset也可以传递给CollectionToList方法,但是通过这种方式,您将从表中加载所有表行,这可能会花费大量时间和内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM