Как повторять список в отражении

У меня есть одно свойство "Студенты", которое имеет тип List<Student>.

В отражении я могу получить значение свойства Students.

Теперь проблема заключается в том, как перебирать список студентов.

Мне нужно проверить, есть ли в этой коллекции StudentID [некоторое значение].

var collection = studentPro.GetValue(studentObj,null);

//I need to iterate like this,

foreach(var item in collection)
{
     if(item.StudentID == 33)
         //Do stuff
}

Пожалуйста, помогите мне.

Ответ 1

Вам просто нужно отличить его:

var collection = (List<Student>) studentPro.GetValue(studentObj,null);

Значение, возвращаемое вам и сохраненное в var, имеет тип object. Поэтому перед тем, как попытаться проскочить через него, нужно сначала направить его на List<Student>.

RANT

Вот почему мне лично не нравится var, он скрывает тип - если только в VS вы не наводите на него курсор. Если он был объявлен с типом object, сразу стало очевидно, что мы не можем его перебирать.


UPDATE

Да, это хорошо. Но кастинг должен быть сделано с отражением. В отражении мы Не знаю тип списка. Мы не знать фактический тип studentObj

Чтобы сделать это, вы можете использовать IEnumerable:

var collection = (IEnumerable) studentPro.GetValue(studentObj,null);

Ответ 2

Попробуйте это

IEnumerable<Student> collection = (IEnumerable<Student>)studentPro.GetValue(studentObj,null);

Ответ 3

Другие предложили листинг в List, но я буду считать, что это не сработает для вас... если бы вы имели доступ к классу Student, вы бы не использовали рефлексию для начала. Таким образом, вместо этого просто добавьте в IEnumerable, а затем внутри своего цикла, вам придется снова использовать отражение для доступа к любым свойствам, которые вы хотите от каждого элемента в коллекции.

var collection = (IEnumerable)studentPro.GetValue(studentObj,null)

Ответ 4

То, как вы пытались, является правильным. Вам просто нужно исправить свой код и вернуть возвращаемое значение из GetValue:

var collection = (List<Student>)studentPro.GetValue(studentObj,null);

foreach(var item in collection)
{
     if(item.StudentID == 33)
         //Do stuff
}

Ответ 5

У вас может быть что-то вроде ниже, чтобы создать объект POCO из вашего прокси-объекта. Обратите внимание, что я полагаюсь на использование атрибута XMLIgnore для разрыва круговых ссылок

static object DeepCopy(object obj, Type targetType)
    {
        if (obj != null)
        {
            Type t = obj.GetType();

            object objCopy = Activator.CreateInstance(targetType);

            Type copyType = targetType;

            var props =
                t.GetProperties();

                    //.Where(x => x.PropertyType.GetCustomAttributes(typeof(XmlIgnoreAttribute), false).Length == 0);
            foreach (var propertyInfo in props)
            {
                var targetProperty = copyType.GetProperties().Where(x => x.Name == propertyInfo.Name).First();

                if (targetProperty.GetCustomAttributes(typeof(XmlIgnoreAttribute), false).Length > 0)
                {
                    continue;
                }

                if (propertyInfo.PropertyType.IsClass)
                {
                    if (propertyInfo.PropertyType.GetInterface("IList", true)!=null)
                    {
                        var list = (IList)Activator.CreateInstance(targetProperty.PropertyType);

                        targetProperty.SetValue(objCopy,list);

                        var sourceList = propertyInfo.GetValue(obj) as IList;

                        foreach (var o in sourceList)
                        {
                            list.Add(DeepCopy(o, targetProperty.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]));
                        }

                    }
                    else if (propertyInfo.PropertyType == typeof(string))
                    {
                        targetProperty.SetValue(objCopy, propertyInfo.GetValue(obj));
                    }
                    else
                    {
                        targetProperty.SetValue(objCopy, DeepCopy(propertyInfo.GetValue(obj), targetProperty.PropertyType));
                    }

                }
                else
                {
                    targetProperty.SetValue(objCopy,propertyInfo.GetValue(obj));
                }
            }

            return objCopy;

        }
        return null;
    }

    class MyDbContext:DbContext
{
    public MyDbContext():base(@"Server=(LocalDb)\v12.0;Trusted_Connection=True;")
    {

    }

    public DbSet<Table1> Table1s { get; set; }

    public DbSet<Table2> Table2s { get; set; }

}

public class Table1
{
    public int ID { get; set; }

    public string name { get; set; }

    virtual public List<Table2> Table2s { get; set; }
}


public class Table2
{
    public int ID { get; set; }

    public string Name { get; set; }
    [XmlIgnore]
    virtual public Table1 Table1 { get; set; }
}