handler | 处理操作的回调函数。接收一个 TFilterVariable(过滤器处理程序返回的值,每个元素都不同)、一个 TFilterConstant(操作符的右侧值,为常量)以及一个 StringComparison 选项,并返回一个布尔值,指示过滤器是否通过。 |
QueryFilterOperator 当前的 QueryFilterOperator。
添加自定义过滤器操作符处理程序。
<TFilterVariable>: 操作符左侧操作数的类型。这是过滤器处理程序返回的类型。
<TFilterConstant>: 操作符右侧操作数的类型。
操作符处理程序是一个针对特定操作符(例如“=”)且具有特定类型要求的函数。操作符处理程序由过滤器处理程序(请参阅 AddFilter)的返回值选择,该过滤器处理程序在解析查询时被识别,以及过滤器的类型。
// Add a new modulo operator on this filter var op = "%"; queryEngine.TryGetFilter("id", out var filter); filter.AddOperator(op) .AddHandler((int ev, int fv) => ev % fv == 0) .AddHandler((float ev, float fv) => Math.Abs(ev % fv) < 0.00000001f);
以下是一个示例,其中我们覆盖了所有涉及字符串的过滤器的“=”操作符的行为,通过执行正则表达式搜索而不是传统的匹配。
using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.Search; using UnityEngine; static class Example_QueryEngine_RegexValue { static QueryEngine<MyObjectType> SetupQueryEngine() { var queryEngine = new QueryEngine<MyObjectType>(); queryEngine.AddFilter("id", myObj => myObj.id); queryEngine.AddFilter("n", myObj => myObj.name); queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name }); // Override the = operators to do a regex match var op = queryEngine.GetOperator("="); op.AddHandler((string ev, string fv) => RegexMatch(fv, ev)); return queryEngine; } static bool RegexMatch(string pattern, string source) { var match = Regex.Match(source, pattern); return match.Success; } static string[] s_Words = new[] { "bob", "cat", "car", "happy", "sad", "squirrel", "pizza", "dog", "over", "bing", "bong" }; static IEnumerable<MyObjectType> GenerateData(int count) { for (var i = 0; i < count; ++i) { var wordCount = Random.Range(1, 6); var words = new List<string>(); for (var j = 0; j < wordCount; ++j) words.Add(s_Words[Random.Range(0, s_Words.Length)]); var name = string.Join(" ", words); var id = $"{Random.Range(0, 1000)}-{s_Words[Random.Range(0, s_Words.Length)]}"; yield return new MyObjectType() { id = id, name = name }; } } static void FilterData(string text, QueryEngine<MyObjectType> queryEngine, IEnumerable<MyObjectType> data) { var query = queryEngine.ParseQuery(text); if (!query.valid) { foreach (var queryError in query.errors) Debug.LogFormat(LogType.Error, LogOption.NoStacktrace, null, $"Error parsing query at position {queryError.index}: {queryError.reason}"); return; } var filteredData = query.Apply(data).ToList(); var escapedText = text.Replace("{", "{{").Replace("}", "}}"); Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, $"Query \"{escapedText}\" yielded {filteredData.Count} result{(filteredData.Count > 1 ? "s" : "")}"); foreach (var filteredObject in filteredData) Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, filteredObject.ToString()); } [MenuItem("Examples/QueryEngine/RegexValue")] public static void RunExample() { // Set up the query engine var queryEngine = SetupQueryEngine(); var data = GenerateData(100); // Find all items with an id that match "^\\d{2}-c.+" (for example, "42-cat" or "99-car") // The quotes are required when using special characters like {}. FilterData("id=\"^\\d{2}-c.+\"", queryEngine, data); // Find all items with a name containing a duplicate (for example, "squirrel cat cat dog" or "pizza pizza dog") // The quotes are required when using special characters like {}. FilterData("n=(\\S+)\\s+(\\1)", queryEngine, data); } class MyObjectType { public string id { get; set; } public string name { get; set; } = string.Empty; public override string ToString() { return $"({id}, {name})"; } } }