2011-06-22 76 views
1

我有一个C#应用程序,其中包含用户界面,其中包含用户可以执行的搜索类型的选项。选项是“多项”(分隔空间上的搜索词),“区分大小写”和“正则表达式”。未来可能会增加更多选项。谓词查找表?

这些选项存储在属性IsMultipleTerms,IsCaseSensitive和IsRegularExpression中。

的选项每个组合具有不同的搜索谓词,和搜索谓词的定义如下所示:

private bool SearchCaseInsensitive(string field) 
{ 
    return field.ToLower().Contains(_searchTermLower); 
} 

private bool SearchCaseInsensitiveMultiple(string field) 
{ 
    return _searchTermsLower.All(field.ToLower().Contains); 
} 

我过滤列表如下所示:

var predicate = GetFilterPredicate(); 

SearchResults.Where(predicate); 

我目前通过使用实现的查找一个名为SearchPredicateOptionSet的类:

public class PredicateOptionSet 
{ 
    public bool IsCaseSensitive { get; set; } 
    public bool IsRegularExpression { get; set; } 
    public bool IsMultipleTerms { get; set; } 

    public Func<SearchResult, bool> Predicate { get; set; } 

    public PredicateOptionSet(bool isCaseSensitive, bool isRegularExpression, bool isMultipleTerms, 
     Func<SearchResult, bool> predicate) 
    { 
     IsCaseSensitive = isCaseSensitive; 
     IsRegularExpression = isRegularExpression; 
     IsMultipleTerms = isMultipleTerms; 

     Predicate = predicate; 
    } 
} 

我创建他们的名单,然后查询它:

private readonly List<PredicateOptionSet> _predicates; 

public MainWindow() 
{ 
    _predicates = new List<PredicateOptionSet> 
    { 
     new PredicateOptionSet(true, false, false, result => Search(result.Name)), 
     new PredicateOptionSet(false, false, false, result => SearchCaseInsensitive(result.Name)), 

     new PredicateOptionSet(true, false, true, result => SearchMultiple(result.Name)), 
     new PredicateOptionSet(false, false, true, result => SearchCaseInsensitiveMultiple(result.Name)), 
    }; 
} 

private Func<SearchResult, bool> GetFilterPredicate() 
{ 
    var predicate = from p in _predicates 
     where p.IsCaseSensitive == IsCaseSensitive && 
      p.IsMultipleTerms == IsMultipleTerms && 
      p.IsRegularExpression == IsRegularExpression 
     select p.Predicate; 

    return predicate.First(); 
} 

有没有更清晰的方式来实现这一目标?我觉得我可能会错过一个重要的概念。

+0

什么是PredicateOptionSet? – asawyer

+0

将其添加到问题主体,对不起:) – Beau

+1

您可以将Predicate 替换为Func ,因为它暗示返回类型为bool。可能远离命名Predicate参数,因为它已经涉及到特定的内容。 –

回答

1

至少对于检查部分,您可以使用Enum和[Flags]属性创建位域。如果您将来添加更多方法,这可能会更具可扩展性。然后,您可以使用简单的查找表并取消类PredicateOptionSet。例如:

[Flags] 
public enum PredicateOption 
{ 
    IsCaseSensitive, IsRegularExpression, IsMultipleTerms 
}; 

...

public Dictionary<PredicateOption, Func<SearchResult, bool>> _predicates 
    = new Dictionary<PredicateOption, Func<SearchResult, bool>>(); 
_predicates.Add(PredicateOption.IsCaseSensitive, result => Search(result.Name)); 
_predicates.Add(PredicateOption.IsCaseSensitive | PredicateOption.IsMultipleTerms, 
    result => SearchCaseInsensitiveMultiple(result.Name)); 

....

PredicateOption option = PredicateOption.IsCaseSensitive | PredicateOption.IsMultipleTerms; 
SearchResults.Where(_predicates[option]); 
0

看来你可以为每个选项创建一个函数,然后链接它们(通过Where(...)调用)。那样,你只有三种方法而不是四种。另外,如果您需要,您可以用更多方式将较小的操作组合在一起。

1

也许我看到它错了,但目前你有2种完全不同的搜索策略:在正常和正则表达式。这两种策略都支持一个选项,不管是否区分大小写,但这可能是策略的一个参数。多重匹配问题已经有点特殊了,因为无论如何您必须首先分割搜索词,然后您可以将其委托回其中一种简单的搜索策略(将搜索与AND或OR结合使用)。

为这些方面的每个组合创建一个单独的Func实现感觉有点“过度杀伤”。如果将来会有更多的选择,那么确实很容易找到一种处理这些选项“一样”的广义方法,但另一方面,这些选项的表现却完全不同。对于未来的扩展,您也会遇到不同实现的组合爆炸。