面向 QueryEngine 过滤器的界面。
在 QueryEngine 中添加新的过滤器后,您会收到一个实现界面 IQueryEngineFilter 的过滤器对象。您可以修改此过滤器来覆盖 QueryEngine 的全局行为。例如,您可以添加针对此过滤器特定的 类型解析器 或 操作符。
using System.Collections.Generic; using System.Globalization; using System.Linq; using UnityEditor; using UnityEditor.Search; using UnityEngine; static class Example_IQueryEngineFilter { static List<MyObjectType> s_Data; static QueryEngine<MyObjectType> SetupQueryEngine() { // Set up the query engine var queryEngine = new QueryEngine<MyObjectType>(); // Add a filter for MyObjectType.position that supports equals and not equals queryEngine.AddFilter("p", myObj => myObj.position, new[] { "=", "!=" }); // Add a new type parser for Vector2 written as "[x, y]", but only for this filter. // This type parser will not affect other filters. queryEngine.TryGetFilter("p", out var filter); filter.AddTypeParser(s => { // If the format requirement is not met, return a failure. if (!s.StartsWith("[") || !s.EndsWith("]")) return ParseResult<Vector2>.none; var trimmed = s.Trim('[', ']'); var vectorTokens = trimmed.Split(','); var vectorValues = vectorTokens.Select(token => float.Parse(token, CultureInfo.InvariantCulture.NumberFormat)).ToList(); if (vectorValues.Count != 2) return ParseResult<Vector2>.none; var vector = new Vector2(vectorValues[0], vectorValues[1]); // When the conversion succeeds, return a success. return new ParseResult<Vector2>(true, vector); }); // Override global operators with specific operator handlers for this filter filter.AddOperator("=").AddHandler((Vector2 ev, Vector2 fv) => ev == fv); filter.AddOperator("!=").AddHandler((Vector2 ev, Vector2 fv) => ev != fv); // Set up what data from objects of type MyObjectType will be matched against search words queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name }); return queryEngine; } [MenuItem("Examples/IQueryEngineFilter/IQueryEngineFilter")] public static void RunExample() { s_Data = GenerateExampleData(); var queryEngine = SetupQueryEngine(); TestFiltering(queryEngine, s_Data); } static void TestFiltering(QueryEngine<MyObjectType> queryEngine, IEnumerable<MyObjectType> inputData) { var vec = new Vector2(1, 0); // Find objects that are at position [1, 0] var filteredData = FilterData("p=[1,0]", queryEngine, inputData); ValidateData(filteredData, s_Data.Where(myObj => myObj.position == vec)); //Find objects that are not at position [1, 0] filteredData = FilterData("p!=[1,0]", queryEngine, inputData); ValidateData(filteredData, s_Data.Where(myObj => myObj.position != vec)); } static IEnumerable<MyObjectType> FilterData(string inputQuery, QueryEngine<MyObjectType> queryEngine, IEnumerable<MyObjectType> inputData) { // Parse the query string into a query operation var query = queryEngine.ParseQuery(inputQuery); // If the query is not valid, print all errors and return an empty data set if (!query.valid) { foreach (var queryError in query.errors) { Debug.LogFormat(LogType.Error, LogOption.NoStacktrace, null, $"Error parsing input at {queryError.index}: {queryError.reason}"); } return new List<MyObjectType>(); } // Apply the query on a data set and get the filtered result. var filteredData = query.Apply(inputData); return filteredData; } static void ValidateData(IEnumerable<MyObjectType> filteredData, IEnumerable<MyObjectType> expectedData) { var filteredDataArray = filteredData.ToArray(); var expectedDataArray = expectedData.ToArray(); Debug.Assert(filteredDataArray.Length == expectedDataArray.Length, $"Filtered data should have {expectedDataArray.Length} elements."); if (filteredDataArray.Length != expectedDataArray.Length) return; for (var i = 0; i < expectedDataArray.Length; i++) { Debug.Assert(filteredDataArray[i] == expectedDataArray[i], $"{filteredDataArray[i]} should be equal to {expectedDataArray[i]}"); } } static List<MyObjectType> GenerateExampleData() { var data = new List<MyObjectType>() { new MyObjectType { id = 0, name = "Test 1", position = new Vector2(0, 0), active = false }, new MyObjectType { id = 1, name = "Test 2", position = new Vector2(0, 1), active = true }, new MyObjectType { id = 2, name = "Test 3", position = new Vector2(1, 0), active = false }, new MyObjectType { id = 3, name = "Test 4", position = new Vector2(1.2f, 0), active = false }, }; return data; } /// <summary> /// Custom type. This is the type of objects that will be searched by the QueryEngine. /// </summary> class MyObjectType { public int id { get; set; } public string name { get; set; } public Vector2 position { get; set; } public bool active { get; set; } public MyObjectType() { id = 0; name = ""; position = Vector2.zero; active = false; } public override string ToString() { return $"({id}, {name}, ({position.x}, {position.y}), {active})"; } } }
metaInfo | 针对过滤器的其他特定信息。 |
operators | 针对过滤器的特定 QueryFilterOperator 集合。 |
overridesStringComparison | 表示过滤器是否覆盖全局字符串比较选项。 |
parameterType | 如果使用,传递给过滤器的常量参数类型。 |
regexToken | 与过滤器匹配的正则表达式。匹配过滤器中操作符前面的内容(例如,在“id>=2”中匹配“id”)。 |
stringComparison | 过滤器的字符串比较选项。 |
supportedOperators | 受支持的操作符列表。 |
token | 过滤器的标识符。通常是过滤器中操作符前面的内容(例如,在“id>=2”中匹配“id”)。 |
type | 过滤器比较的数据类型。 |
usesParameter | 表示过滤器是否使用参数。 |
usesRegularExpressionToken | 表示过滤器是否使用正则表达式令牌。 |
usesResolver | 表示过滤器是否使用解析器函数。 |
AddOperator | 针对过滤器添加特定自定义过滤器操作符。 |
AddOrUpdateMetaInfo | 针对过滤器添加或更新其他特定信息。 |
AddTypeParser | 针对过滤器添加特定类型解析器。 |
ClearMetaInfo | 删除针对过滤器的所有其他特定信息。 |
RemoveMetaInfo | 删除关于过滤器的信息。 |
RemoveOperator | 删除针对过滤器特定的自定义操作符。 |
设置嵌套查询转换器 | 设置过滤器的嵌套查询转换器函数。此函数获取嵌套查询结果,并提取与过滤器进行比较的必要数据。 |