我有一个名为NodeUpgrade
的基类,它有几种子类型。特定子类的示例是FactoryUpgrade
。
我有一个NodeUpgrades列表,它可以是不同子类型的混合。如何编写linq查询以检索NodeUpgrade
类型并转换为该特定类型?
我的工作查询看起来像这样:
var allFactories = (from Node n in assets.Nodes
from FactoryUpgrade u in n.NodeUpgrades
where u.ClassID == NodeUpgradeTypes.Factory
select u)
当然,这不起作用。我可以指定输出的最终类型吗?
答案 0 :(得分:4)
如果您确定序列中的每个类型都是给定类型,则可以使用Cast<T>()
扩展方法。如果列表中可以有多种类型,并且您只需要其中一种类型,则可以使用OfType<T>()
来过滤序列。
List<Animal> animals = ...
// assumes all animals are cats
var cats = animals.Cast<Cat>();
// var cats = (from animal in animals where ... select animal).Cast<Cat>();
// or maybe animals can contain dogs, but you don't want them
var cats = animals.OfType<Cat>();
不同之处在于,如果动物不是猫,Cast
会抛出异常,而OfType
会在实际尝试转换之前执行类型检查。当你对统一类型有信心时,我会赞成Cast
超过OfType
。 (另请注意,这些不执行用户定义的转换。如果已定义隐式或显式转换,则这些方法将不支持这些转换。)
每种情况下生成的序列都是IEnumerable<Cat>
,您可以对其进行进一步的查询操作(过滤器,分组,投影,ToList()
等)。
答案 1 :(得分:1)
您可以使用方法OfType<>
var allFactories = (from Node n in assets.Nodes
from FactoryUpgrade in n.NodeUpgrades
where u.ClassID == NodeUpgradeTypes.Factory
select u).OfType<ChildType>();
答案 2 :(得分:1)
正如其他人所说,使用.OfType扩展方法来过滤类型(假设您已在数据源上设置了继承模型和适当的鉴别器)。这将在数据库中转换为在鉴别器(ClassID)上包含适当的Where子句。
var allFactories = from n in assets.Nodes
from u in n.NodeUpgrades.OfType<FactoryUpgrade>()
select u;
在这种情况下,您没有在此处指定是使用EF,LINQ to SQL还是仅使用Linq to Objects。每种方法都有不同的继承建模方式。如果您需要有关建模部分的帮助,请告诉我们您正在使用的OR / M.