Как перебрать список в отражении - PullRequest
12 голосов
/ 10 мая 2011

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

В рефлексии я могу получить значение свойства Студенты.

Теперь проблема в том, как выполнить итерацию списка.of 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
}

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

Ответы [ 5 ]

15 голосов
/ 10 мая 2011

Вам просто нужно разыграть это:

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

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

RANT

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


UPDATE

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

Для этого вы можете привести к IEnumerable:

var collection = (IEnumerable) studentPro.GetValue(studentObj,null);
2 голосов
/ 10 мая 2011

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

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

2 голосов
/ 10 мая 2011

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

IEnumerable<Student> collection = (IEnumerable<Student>)studentPro.GetValue(studentObj,null);
1 голос
/ 10 мая 2011

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

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

foreach(var item in collection)
{
     if(item.StudentID == 33)
         //Do stuff
}
0 голосов
/ 15 сентября 2016

Вы можете создать что-то подобное ниже, чтобы создать объект 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; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...