op | 过滤器运算符。 |
handler | 处理该操作的回调。采用 TFilterVariable(过滤器处理程序返回的值,因每个元素而异)、TFilterConstant(运算符的常量右侧值)和 StringComparison 选项,并返回一个指示过滤器是否通过或不通过的布尔值。 |
添加自定义过滤器运算符处理程序。
<TFilterVariable>:运算符左侧操作数的类型。这是过滤器处理程序返回的类型。
<TFilterConstant>:运算符右侧操作数的类型。
运算符处理程序是一个针对具有特定类型要求的特定运算符(例如“=”)执行的函数。运算符处理程序是由过滤器处理程序的返回值(参见 AddFilter)选择的,该值在解析查询时标识,以及过滤器值的类型。
此函数可用于向新自定义运算符添加运算符处理程序(完整示例参见 AddOperator)
// Add a new operator token const string op = "%"; queryEngine.AddOperator(op); // Define what this operator does, and which types it operates on. queryEngine.AddOperatorHandler(op, (int ev, int fv) => ev % fv == 0);
但它也可用于在现有运算符上注册新的运算符处理程序
using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.Search; using UnityEngine; static class Example_QueryEngine_AddOperatorHandler { static List<MyObjectType> s_Data; [MenuItem("Examples/QueryEngine/AddOperatorHandler")] public static void RunExample() { // Set up the query engine var queryEngine = new QueryEngine<MyObjectType>(); queryEngine.AddFilter("id", myObj => myObj.id); queryEngine.AddFilter("prop", myObj => myObj.property); queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name }); // Set the global string comparison options (default is OrdinalIgnoreCase) queryEngine.SetGlobalStringComparisonOptions(StringComparison.Ordinal); // Define new handlers for existing operators, but with new types queryEngine.AddOperatorHandler("=", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue == filterValue)); queryEngine.AddOperatorHandler("!=", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue != filterValue)); queryEngine.AddOperatorHandler("<", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue < filterValue)); queryEngine.AddOperatorHandler(">", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue > filterValue)); queryEngine.AddOperatorHandler("<=", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue <= filterValue)); queryEngine.AddOperatorHandler(">=", (Property ev, int fv) => HandleIntType(ev, fv, (propValue, filterValue) => propValue >= filterValue)); // New handlers with support for the global string comparison options queryEngine.AddOperatorHandler(":", (Property ev, string fv, StringComparison options) => HandleStringType(ev, fv, (propValue, filterValue) => propValue.IndexOf(filterValue, options) >= 0)); queryEngine.AddOperatorHandler("=", (Property ev, string fv, StringComparison options) => HandleStringType(ev, fv, (propValue, filterValue) => propValue.Equals(filterValue, options))); queryEngine.AddOperatorHandler("!=", (Property ev, string fv, StringComparison options) => HandleStringType(ev, fv, (propValue, filterValue) => !propValue.Equals(filterValue, options))); s_Data = new List<MyObjectType>() { new MyObjectType { id = 0, property = new Property("size", PropertyType.Integer, 64) }, new MyObjectType { id = 1, property = new Property("size", PropertyType.Integer, 128) }, new MyObjectType { id = 2, property = new Property("tag", PropertyType.String, "item") }, new MyObjectType { id = 3, property = new Property("tag", PropertyType.String, "car item") }, new MyObjectType { id = 3, property = new Property("tag", PropertyType.String, "42") } }; // Find all items that have a property with an integer value < 100 var query = queryEngine.ParseQuery("prop<100"); var filteredData = query.Apply(s_Data).ToList(); Debug.Assert(filteredData.Count == 1, $"There should be 1 item in the filtered list but found {filteredData.Count} items."); Debug.Assert(filteredData.Contains(s_Data[0]), "Test 1 should be in the list as its property value is < 100."); // Find all items that have a property with a string value that contains "Item". // In this case, since the comparison option is Ordinal, we test the casing. query = queryEngine.ParseQuery("prop:Item"); filteredData = query.Apply(s_Data).ToList(); Debug.Assert(filteredData.Count == 0, $"There should be 0 item in the filtered list but found {filteredData.Count} items."); } static bool HandleIntType(Property prop, int value, Func<int, int, bool> operatorHandler) { if (prop.type != PropertyType.Integer) return false; if (!(prop.value is int i)) return false; return operatorHandler(i, value); } static bool HandleStringType(Property prop, string value, Func<string, string, bool> operatorHandler) { if (prop.type != PropertyType.String) return false; if (!(prop.value is string s)) return false; return operatorHandler(s, value); } enum PropertyType { Integer, String } struct Property { public string name { get; } public PropertyType type { get; } public object value { get; set; } public Property(string name, PropertyType type, object value) { this.name = name; this.type = type; this.value = value; } } class MyObjectType { public int id { get; set; } public string name { get; set; } = string.Empty; public Vector2 position { get; set; } = Vector2.zero; public bool active { get; set; } public Property property { get; set; } public override string ToString() { return $"({id}, {name}, ({position.x}, {position.y}), {active})"; } } }