在反射期间使用LINQ访问底层类型

时间:2013-02-22 23:29:19

标签: .net linq reflection

我有自己的小应用程序来实现http://projecteuler.net问题的解决方案。我有一个名为ProblemBase的基类,它包含有关问题的元信息,例如它们的id,名称和描述文本以及解算器函数。然后,每个问题实现都来自这个类。

现在实现的列表变得非常大,所以我没有手动维护解决方案容器,而是第一次走进了反射区域。我的想法是在程序集中找到从ProblemBase派生的所有类型,并将它们实例化为应用程序的问题枚举(下面代码中的Problems),这样我就可以从我的GUI中与它们进行交互。这是我目前的实施:

    private void FindProblemTypes()
    {
        var problemBaseType = typeof(ProblemBase);
        var problemTypes = (from t in Assembly.GetAssembly(problemBaseType).GetTypes()
                            where t != problemBaseType && problemBaseType.IsAssignableFrom(t)
                            select t).ToList();

        Problems = new ObservableCollection<ProblemBase>();
        foreach (var problemType in problemTypes)
        {
            Problems.Add((ProblemBase)Activator.CreateInstance(problemType));
        }

        Problems = new ObservableCollection<ProblemBase>(Problems.OrderBy(t => t.Id));
    }

它正在工作,但我想清理一下。现在,我首先创建一个派生类型的列表,然后将它们安装到我的集合中,然后再创建另一个集合,按照它们的id来排序类型。我想要做的是直接从第一个LINQ集合创建我的ObservableCollection。我想在LINQ语句中添加orderby t.Id,但由于类型集合包含System.Type个对象而不是ProblemBase个对象,因此该属性不可用,我无法转换变量到LINQ查询中的基础对象。我假设它是因为我要求的类型信息在编译时是不知道的,但有没有其他方法可以像查询中的ProblemBase对象那样对待它?或者我必须坚持我拥有的东西?

1 个答案:

答案 0 :(得分:0)

var problemTypes = (from t in Assembly.GetAssembly(problemBaseType).GetTypes()
    where t != problemBaseType && problemBaseType.IsAssignableFrom(t)
    select (ProblemBase)Activator.CreateInstance(t)).ToList().OrderBy(t => t.Id);

这会起作用吗?你仍然需要使用AddRange将它放入你的集合中,但这不会迭代它们,所以没关系。我不是LINQ中最好的,所以你可能想测试一下。

我认为你永远不会把你的“orderby id”塞进原始查询中,因为当时这些项目都不会被创建。