简体   繁体   English

如何迭代List <T> 其中T:MyClass

[英]How to iterate List<T> where T: MyClass

I have entity with nested list: 我有嵌套列表的实体:

public class Article : MyEntityBase
{
    public Article()
    {
        Tags = new List<Tag>();
    }

    [MyAttribute]
    public string Title { get; set; }

    [MyAttribute]
    public virtual List<Tag> Tags { get; set; }
}

public class Tag : EntityBase
{
    public string Title { get; set; }
}

public abstract class MyEntityBase
{
    public Guid Id { get; set; }
}

Also I have function that collects all [MyAttribute] marked properties and do something operations with them: 此外,我还有一个函数,它收集所有[MyAttribute]标记的属性并对它们执行一些操作:

public function OperateWithAttributes(IEnumerable<PropertyInfo> properties)
{
    foreach (var p in properties)
    {
        if (p.PropertyType == typeof(string))
        {
            // do something
        }
        else if (/* there are code that check property type is List<T> */)
        {
            /* there are code that iterate list */
        }
    }
}

Questions: 问题:

  • How to compare property type with List<T> ? 如何比较属性类型与List<T>
  • How to iterate list if I know that it's inherited from EntityBase ? 如果我知道它是从EntityBase继承的,如何迭代列表?

PS PS

I'm using .NET 4.5 我正在使用.NET 4.5

How to compare property type with List<T> ? 如何比较属性类型与List<T>

Correctly identifying something as a list is ... tricky; 正确地将某事物识别为列表是......棘手的; especially if you want to handle all edge-cases (a custom IList<Foo> implementation, or a class that subclasses List<T> , etc). 特别是如果你想处理所有边缘情况(自定义IList<Foo>实现,或者子类List<T>类等)。 A lot of framework code checks instead for "implements the non-generic IList , and has a non- object indexer": 许多框架代码检查“实现非通用IList ,并具有非object索引器”:

    static Type GetListType(Type type)
    {
        if (type == null) return null;
        if (!typeof(IList).IsAssignableFrom(type)) return null;

        var indexer = type.GetProperty("Item", new[] { typeof(int) });
        if (indexer == null || indexer.PropertyType == typeof(object))
            return null;

        return indexer.PropertyType;
    }

How to iterate list if I know that it's inherited from EntityBase ? 如果我知道它是从EntityBase继承的,如何迭代列表?

Assuming you mean that the items are inherited from EntityBase , and you have determined that it is a list (from the previous question), then the easiest option is IList and foreach : 假设你的意思是这些是从EntityBase继承的,并且你已经确定它是一个列表(来自上一个问题),那么最简单的选项是IListforeach

var itemType = GetListType(p.PropertyType);
if(itemType != null && itemType.IsSubclassOf(typeof(EntityBase)))
{
    var list = (IList) p.GetValue(obj);
    foreach(EntityBase item in list)
    {
        // ...
    }
}

Note: if you are going to get the value anyway , you can also reverse this and use an is test before using GetListType : 注意:如果你打算无论如何要得到值,还可以扭转这种和使用is 使用之前测试GetListType

var value = p.GetValue(obj);
Type itemType;
if(value is IList && (itemType = GetListType(p.PropertyType) != null)
      && itemType.IsSubclassOf(typeof(EntityBase)))
{
    var list = (IList)value;
    foreach(EntityBase item in list)
    {
        // ...
    }
}

How to compare property type with List<T> : 如何比较属性类型与List<T>

if (p.PropertyType.IsGenericType && 
    p.PropertyType.GetGenericTypeDefinition() == typeof(List<>))

How to iterate list if I know that [its items are] inherited from EntityBase: 如果我知道[其项目]是从EntityBase继承的,如何迭代列表:

var listForIteration = (IEnumerable<EntityBase>)list;

foreach (var item in listForIteration)
{
}

A List<T> is not covariant, but (as of .NET 4.0) an IEnumerable<T> is. List<T>不是协变的,但是(从.NET 4.0开始) IEnumerable<T>是。

UPDATE : After some comments, here's an answer to the question you didn't ask: 更新 :经过一些评论,这里是你没有问过的问题的答案:

How to test if I can enumerate an object as a sequence of items that inherit from EntityBase, and if so, loop over it: 如何测试我是否可以将对象枚举为从EntityBase继承的项目序列,如果是,则循环遍历它:

var listForIteration = list as IEnumerable<EntityBase>;

if (listForIteration != null)
{
    foreach (var item in listForIteration)
    {
    }
}

This will (on .NET 4.0 or later) allow you to iterate any collection of EntityBase (or derived) objects, even if the collection is not a List<> (except for those that don't implement IEnumerable<T> , but those are rare). 这将(在.NET 4.0或更高版本上)允许您迭代任何EntityBase(或派生)对象的集合,即使该集合不是List<> (除了那些没有实现IEnumerable<T>那些,但那些很少见)。

You probably want something like 你可能想要这样的东西

Type type = p.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>) &&
   typeof(EntityBase).IsAssignableFrom(type.GetGenericArguments()[0]))
{
    // iterate list
}

If you only want to iterate the list, you can use IEnumerable<out T> 's covariance: 如果您只想迭代列表,可以使用IEnumerable<out T>的协方差:

if (typeof(IEnumerable<EntityBase>).IsAssignableFrom(p.PropertyType))
{
    var enumerable = (IEnumerable<EntityBase>)p.GetValue(obj);
    foreach (var entity in entities)
    {
        // do something
    }
}

How to iterate list if I know that it's inherited from EntityBase? 如果我知道它是从EntityBase继承的,如何迭代列表?

You know it's a subclass of type EntityBase , so instead of using generics, why not just go for a good old superclass reference? 你知道它是EntityBase类型的子类,所以不是使用泛型,为什么不去寻找一个好的旧超类引用呢? Then there's no need to use generics in this scenario, when List<EntityBase> will do fine. 然后在这种情况下,当List<EntityBase>良好时,不需要使用泛型。

为什么我不能从列表中投射<myclass>列出<object> ?<div id="text_translate"><p> 我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List&lt;object&gt;的方法。</p><p> 我的代码行显示...</p><pre> Tools.MyMethod((List&lt;object&gt;)MyListOfQuoteHeaders);</pre><p> 但是我在设计时收到以下错误...</p><pre> Cannot convert type 'System.Collections.Generic.List&lt;MyNameSpace.QuoteHeader&gt;' to 'System.Collections.Generic.List&lt;object&gt;'</pre><p> 我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?</p></div></object></myclass> - Why can't I cast from a List<MyClass> to List<object>?

暂无
暂无

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

相关问题 带列表的用户控件 <myclass> 无法识别myclass中的公共财产 - Usercontrol with List<myclass> doesn't recognize public properties in myclass 公共 T GetMyClass<t> () where T: MyClass, new() { /* 这没有意义吗? */ }</t> - public T GetMyClass<T>() where T : MyClass, new() { /* is this pointless? */ } 在哪里以及如何存储清单 <myClass> 有喜好吗? - Where and how store List<myClass> with preferences? 投射我的课堂<T>到我的课堂<dynamic> - Cast MyClass<T> to MyClass<dynamic> 保持字典 <Type, MyClass<T> &gt;哪些元素可按类型引用 - Keep a Dictionary<Type, MyClass<T>> where elements are referenceable by type 为什么我不能从列表中投射<myclass>列出<object> ?<div id="text_translate"><p> 我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List&lt;object&gt;的方法。</p><p> 我的代码行显示...</p><pre> Tools.MyMethod((List&lt;object&gt;)MyListOfQuoteHeaders);</pre><p> 但是我在设计时收到以下错误...</p><pre> Cannot convert type 'System.Collections.Generic.List&lt;MyNameSpace.QuoteHeader&gt;' to 'System.Collections.Generic.List&lt;object&gt;'</pre><p> 我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?</p></div></object></myclass> - Why can't I cast from a List<MyClass> to List<object>? 铸造MyClass <T> 到MyClass <object> C# - Casting MyClass<T> to MyClass<object> C# 定义一个类MyClass <T> 或函数MyFunction <T> (T x)其中T只能通过实现IMyInterface的类型 - Define a class MyClass<T> or a function MyFunction<T>(T x) where T can only by a type that implements IMyInterface C#将一个Func <T,List <myClass >>数组传递给一个方法 - C# Passing an array of Func<T, List<myClass>> to a method 名单 <T> &哪里T: - List<T> & where T :
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM