版本:Unity 6 (6000.0)
语言英语
  • C#

QueryEngine<T0>.AddOperatorHandler

建议更改

成功!

感谢你帮助我们提高 Unity 文档的质量。虽然我们无法接受所有提交,但我们会阅读用户提出的每项建议更改,并在适用时进行更新。

关闭

提交失败

由于某些原因,你的建议更改无法提交。请在几分钟后<a>重试</a>。感谢你花时间帮助我们提高 Unity 文档的质量。

关闭

取消

声明

public void AddOperatorHandler(string op, Func<TFilterVariable,TFilterConstant,bool> handler);

声明

public void AddOperatorHandler(string op, Func<TFilterVariable,TFilterConstant,stringComparison,bool> handler);

参数

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})";
        }
    }
}