【问题标题】:How to iterate the List in Reflection如何在反射中迭代列表
【发布时间】:2021-02-20 20:36:12
【问题描述】:

我有一个名为 Students 的属性,其类型为 List<Student>

在反射中我可以得到学生属性的值。

现在的问题是如何迭代学生列表。

我需要检查 StudentID [ some value ] 是否在该集合中。

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

//I need to iterate like this,

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

请帮帮我。

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    您只需要投射它:

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

    返回给您并存储在var 中的值是object 类型。因此,您需要先将其转换为 List&lt;Student&gt;,然后再尝试遍历它。

    咆哮

    这就是我个人不喜欢var 的原因,它隐藏了类型 - 除非在 VS 中将鼠标悬停在它上面。如果它是一个类型为 object 的声明,那么很明显我们无法遍历它。


    更新

    是的,它很好。但铸造应该是 用反射完成。在反思中我们 不知道列表的类型。我们不 知道 studentObj 的实际类型

    为了做到这一点,你可以投到IEnumerable

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

    【讨论】:

    • 是的,很好。但是铸造应该通过反射来完成。在反思中,我们不知道 List> 的类型。我们不知道 studentObj 的实际类型。
    • 尝试此操作时出现错误 - 使用泛型类型 'System.Collections.Generic.IEnumerable' 需要 1 个类型参数。
    • Jagan - 您发布的错误很明显它需要一个类型。此外,如果您不了解如何操作,则不应使用您使用的方法(考虑到您的代码在概念上是正确的,除了您忘记投射东西的事实)。
    • 好的。反思一下,只要考虑我有一个对象,但没有它的类型。如果该对象是 Collection 我需要迭代它并需要打印所有值。
    【解决方案2】:

    试试这个

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

    【讨论】:

      【解决方案3】:

      其他人建议强制转换为 List,但我认为这对您不起作用...如果您可以访问 Student 类,那么您一开始就不会使用反射。因此,只需强制转换为 IEnumerable,然后在循环中,您就必须再次使用反射来访问集合中每个项目所需的任何属性。

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

      【讨论】:

      • 尝试此操作时出现错误 - 使用泛型类型 'System.Collections.Generic.IEnumerable' 需要 1 个类型参数
      • 试试(System.Collections.IEnumerable)
      • 那会解决他的问题。虽然我质疑的是自己无法解决这么简单的问题。他真的不应该使用通用集合。
      【解决方案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; }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-01
          • 2022-01-01
          相关资源
          最近更新 更多