将具有通用参数的项列表拆分为每个泛型类型的单独列表

时间:2015-01-24 00:32:26

标签: c# linq generics

我试图解决一个问题,我想根据列表中项目的泛型参数的类型拆分列表。每种类型的类型可能不同。下面是一些演示代码,试图解释我需要做什么。

注意:此代码将按原样编译,因为在FindDerivedItemsAndCallForEachT中未定义类型T.

using System.Collections.Generic;
using System.Linq;

public class BaseItem
{
}

public class DerivedItem<T> : BaseItem
{
}

public class Test
{
    public void FindDerivedItemsAndCallForEachT(List<BaseItem> list)
    {
        var derivedItems = from d in list.OfType<DerivedItem<T>>()
            select d;

        var listsOfDerivedItems = from d in derivedItems
            group d by d.GetType() into g
            select g.ToList();

        foreach (var listOfDerivedItem in listsOfDerivedItems)
        {
            HandleForTypeT(listOfDerivedItem);
        }
    }


    public void HandleForTypeT<T>(List<DerivedItem<T>> derivedList)
    {
        // do something with the provided list.
    }
}

所以我有一个BaseItems列表,它可能包含一些带有泛型参数的派生项。对于列表中的每个项目,此参数可能不同。我想要做的是在列表中找到所有派生类型,然后将它们拆分为每个泛型类型的单独列表。然后取出每个列表并将它们传递给另一个方法进行处理。

我的方法在这里可能完全错误,所以请随意采取另一条道路。

我的问题与this question几乎相同。我的不同之处在于,我不想在列表项上调用方法,而是将它们作为列表传递给另一个方法。每种类型T的派生项需要一起处理。

1 个答案:

答案 0 :(得分:0)

我有一个&#34;解决方案&#34;。它使用反射,但(如@Jon所述)真正的问题可能是架构本身。我的解决方案可能会有所不同,因为方法HandleForType&lt; T>实际上将在一个单独的类型T中,并且能够过滤List&lt; BaseItem&gt;找到所有Derived&lt; T>本身。

请随意改进代码,因为它可能会帮助其他人尝试做类似的事情。

参考文献:
SO Question that got me on the right track
Related MSDN documentation

using System;
using System.Collections.Generic;
using System.Linq;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class CheckFindDerivedItemsAndCallForEachT
    {
        [TestMethod]
        public void TestMethod1()
        {
            var list = new List<BaseItem>();
            list.Add(new DerivedItem<string>());
            list.Add(new DerivedItem<int>());

            var test = new Test();

            test.FindDerivedItemsAndCallForEachT(list);
        }
    }

    public class BaseItem
    {
    }

    public class DerivedItem<T> : BaseItem
    {
    }

    public class Test
    {
        public void FindDerivedItemsAndCallForEachT(List<BaseItem> list)
        {
            var derivedItems = from d in list
                               where d.GetType().IsGenericType
                               && d.GetType().GetGenericTypeDefinition() == typeof(DerivedItem<>)
                               select d;

            var listsOfDerivedItems = from d in derivedItems
                                      group d by d.GetType() into g
                                      select g.ToList();

            // create generic type definition for lists
            var listGenericDefinition = typeof(List<>);

            foreach (var listOfDerivedItem in listsOfDerivedItems)
            {
                // all the lists should have at least one member which will be of the type that we need.
                Type itemType = listOfDerivedItem[0].GetType();
                Type listType = listGenericDefinition.MakeGenericType(itemType);

                // note use of dynamic is important.
                dynamic castList = Activator.CreateInstance(listType);
                foreach (dynamic item in listOfDerivedItem)
                {
                    castList.Add(item);
                }

                HandleForTypeT(castList);
            }
        }

        public void HandleForTypeT<T>(List<DerivedItem<T>> derivedList)
        {
            // do something with the provided list.
        }
    }
}