我有一个从ProfileBase派生的列表。此列表可以包含Profile,DynamicViewProfile的实例,因为它们都是从ProfileBase派生的
但是如果项目类型是DynamicViewProfile,我必须使用NodeName,如果是Profile,那么我应该使用DocName
profileListsForSearch = profileLists.Where(stringToCheck =>
((Profile)stringToCheck).DocName.Contains(searchBar.Text)).ToList();
所以这是用于配置文件,它没关系,但如果列表包含DynamicViewProfile对象,那么我有一个例外,因为docname为null,我需要获取NodeName
我希望我的问题很清楚
答案 0 :(得分:7)
这里没有什么特别的LINQ - 您基本上使用is
或as
编写与通常相同的代码:
string searchText = searchBar.Text;
profileListsForSearch = profileLists
.Where(profile =>
profile is Profile
? ((Profile)profile).DocName.Contains(searchText)
: ((DynamicViewProfile)profile).NodeName.Contains(searchText))
.ToList();
假设这些是唯一涉及的两种类型。如果您的列表包含其他类型,则会获得InvalidCastException
。
然而,这非常难看 - 感觉ProfileBase
应该公开一些指示通用名称的属性或方法 - 然后可以实现它以在DocName
中返回Profile
并且NodeName
中的DynamicViewProfile
。那么你只需要:
string searchText = searchBar.Text;
profileListsForSearch = profileLists
.Where(profile => profile.Name.Contains(searchText))
.ToList();
它在添加ProfileBase
的新子类方面也具有前瞻性 - 并且通常更清晰地使用多态性。每当你需要施放 - 特别是有条件地施放到一个或另一个 - 考虑一个共同的方法/属性是否可行,使其更清洁。
答案 1 :(得分:1)
您可以使用is
检查对象,并使用ternary
运算符在对象上应用条件。
var result = profileLists.Where(stringToCheck =>stringToCheck is Profile ?
((Profile)stringToCheck).DocName.Contains(searchBar.Text)
: ((DynamicViewProfile)stringToCheck).NodeName.Contains(searchBar.Text)).ToList();
答案 2 :(得分:1)
profileListsForSearch = profileLists.Where(p =>
{
if(p is Profile) return ((Profile)p).DocName.Contains(searchBar.Text));
if(p is DynamicViewProfile) return ((DynamicViewProfile)p).NodeName.Contains(searchBar.Text));
return false;
}).ToList();
您可以查看类型。但这实际上只意味着您的类层次结构被破坏了。如果你得出,你永远不应该被迫明确地检查一个类型。
相反,您可以在基类中使用名为FilterText
的属性,该属性由基类实现为return DocName;
,派生类实现为return NodeName;
。然后你的代码看起来像这样:
profileListsForSearch = profileLists.Where(p => p.FilterText.Contains(searchBar.Text)).ToList();