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

QueryEngine<T0>.AddFilter

提出变更

成功!

感谢您帮助我们改善 Unity 文档的质量。尽管我们无法接受所有提交,但我们会阅读用户提供的每条变更建议,并在适用时进行更新。

关闭

提交失败

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

关闭

取消

声明

public void AddFilter(string token, Func<TData,TFilter> getDataFunc, string[] supportedOperatorType);

声明

public void AddFilter(string token, Func<TData,TFilter> getDataFunc, stringComparison stringComparison, string[] supportedOperatorType);

参数

token 筛选器的标识符。通常为筛选器中操作符前面的部分(例如,“id>=2”中的“id”)。
getDataFunc 用于获取用于筛选的对象的回调。获取类型为 TData 的对象并返回类型为 TFilter 的对象。
stringComparison 字符串比较选项。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。

说明

添加新的自定义筛选器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

如果您不需要自行处理运算符,请使用此重载注册基本筛选器。

// Add a filter for MyObjectType.id that supports all operators
queryEngine.AddFilter("id", myObj => myObj.id);
// Add a filter for MyObjectType.name that supports only contains (:), equal (=) and not equal (!=)
queryEngine.AddFilter("n", myObj => myObj.name, new[] { ":", "=", "!=" });
// Add a filter for MyObjectType.active that supports only equal and not equal
queryEngine.AddFilter("a", myObj => myObj.active, new[] { "=", "!=" });
// Add a filter for the computed property magnitude that supports equal, not equal, lesser, greater, lesser or equal and greater or equal.
queryEngine.AddFilter("m", myObj => myObj.position.magnitude, new[] { "=", "!=", "<", ">", "<=", ">=" });

有关完整示例,请参阅 QueryEngine


声明

public void AddFilter(string token, Func<TData,TParam,TFilter> getDataFunc, string[] supportedOperatorType);

声明

public void AddFilter(string token, Func<TData,TParam,TFilter> getDataFunc, stringComparison stringComparison, string[] supportedOperatorType);

声明

public void AddFilter(string token, Func<TData,TParam,TFilter> getDataFunc, Func<string,TParam> parameterTransformer, string[] supportedOperatorType);

声明

public void 添加过滤器(string 令牌, Func<TData,TParam,TFilter> getDataFunc, Func<string,TParam> parameterTransformer, stringComparison stringComparison, string[] 支持的操作员类型);

参数

token 筛选器的标识符。通常为筛选器中操作符前面的部分(例如,“id>=2”中的“id”)。
getDataFunc 用于获取过滤器中使用的对象的回调。获取一个 TData 和 TParam 类型的对象,并返回一个 TFilter 类型的对象。
parameterTransformer 用于将字符串转换成 TParam 类型的回调。解析查询时使用,将传递给函数的内容转换成正确的格式。
stringComparison 字符串比较选项。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。

说明

添加一个带参数的新自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

<TParam>:传递给过滤器的的数据类型。

如果不需要自行处理运算符,请使用此重载注册接受参数的过滤器。

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Param
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Param")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });

        // Add a "dist" filter to filter items based on a specified distance from a position or from another item
        queryEngine.AddFilter("dist", (myObj, paramPosition) =>
        {
            // Compute the distance from the position that was retrieved in the parameter transformer
            var vec = myObj.position - paramPosition;
            return vec.magnitude;
        }, paramStringValue =>
            {
                // Transform the parameter from a string to a usable Vector2

                // If the user specified a vector
                if (paramStringValue.StartsWith("[") && paramStringValue.EndsWith("]"))
                {
                    paramStringValue = paramStringValue.Trim('[', ']');
                    var vectorTokens = paramStringValue.Split(',');
                    var vectorValues = vectorTokens.Select(token => float.Parse(token, CultureInfo.InvariantCulture.NumberFormat)).ToList();
                    return new Vector2(vectorValues[0], vectorValues[1]);
                }

                // Treat the value as the name of an object
                var myObj = s_Data.Find(obj => obj.name == paramStringValue);
                return myObj.position;
            }, new[] { "=", "!=", "<", ">", "<=", ">=" });

        s_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 },
        };

        // Find all items that are at a distance of 1 or greater to [0, 0]
        var query = queryEngine.ParseQuery("dist([0, 0])>=1");
        var filteredData = query.Apply(s_Data).ToList();
        Debug.Assert(filteredData.Count == 3, $"There should be 3 items in the filtered list but found {filteredData.Count} items.");
        Debug.Assert(!filteredData.Contains(s_Data[0]), "Test 1 should not be in the list as its distance to [0, 0] is < 1.");

        // Find all items that are at a distance smaller than 1 to "Test 3", but not "Test 3" itself
        query = queryEngine.ParseQuery("dist(Test 3)<1 -\"Test 3\"");
        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[3]), "Test 4 should be in the list as its distance to Test 3 is < 1.");
    }

    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 override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}


声明

public void 添加过滤器(string 令牌, Func<TData,string,TFilter,bool> filterResolver, string[] 支持的操作员类型);

参数

token 筛选器的标识符。通常为筛选器中操作符前面的部分(例如,“id>=2”中的“id”)。
filterResolver 用于处理此过滤器的任何运算符的回调。获取一个 TData 类型的对象、运算符令牌和过滤器值,并返回一个布尔值指示过滤器是否已通过或未通过。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。

说明

添加一个带完整解析器的自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

如果需要自行处理运算符,请使用此重载注册基本过滤器。

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Resolver
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Resolver")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });

        // Add a custom filter "is", with a resolver that will handle all operators
        queryEngine.AddFilter<string>("is", (myObj, operatorToken, filterValue) =>
        {
            if (operatorToken != ":")
                return false;

            switch (filterValue)
            {
                case "active":
                    return myObj.active;
                case "root":
                    return myObj.id == 0;
                case "center":
                    return myObj.position == Vector2.zero;
                default: return false;
            }
        }, new[] {":"});

        s_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 },
        };

        // Find all items that are of type "active"
        var query = queryEngine.ParseQuery("is:active");
        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[1]), "Test 2 should be in the list as it is active.");

        // Find all items that are root
        query = queryEngine.ParseQuery("is:root");
        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 it is a root.");
    }

    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 override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}


声明

public void 添加过滤器(string 令牌, Func<TData,TParam,string,TFilter,bool> filterResolver, string[] 支持的操作员类型);

声明

public void 添加过滤器(string 令牌, Func<TData,TParam,string,TFilter,bool> filterResolver, Func<string,TParam> parameterTransformer, string[] 支持的操作员类型);

参数

token 筛选器的标识符。通常为筛选器中操作符前面的部分(例如,“id>=2”中的“id”)。
filterResolver 用于处理此过滤器的任何运算符的回调。获取一个 TData 类型的对象、一个 TParam 类型的对象、运算符令牌和过滤器值,并返回一个布尔值指示过滤器是否已通过或未通过。
parameterTransformer 用于将字符串转换成 TParam 类型的回调。解析查询时使用,将传递给函数的内容转换成正确的格式。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。

说明

添加一个带参数和完整解析器的自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

<TParam>:传递给过滤器的的数据类型。

如果需要自行处理运算符,请使用此重载注册接受参数的过滤器。

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Param_Resolver
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Param_Resolver")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });

        // Add a "dist" filter to filter items based on a specified distance from a position or from another item, and handle all operators
        queryEngine.AddFilter<Vector2, string>("dist", (myObj, paramPosition, operatorToken, filterValue) =>
        {
            var distance = (myObj.position - paramPosition).magnitude;

            if (operatorToken == ":")
            {
                switch (filterValue)
                {
                    case "near":
                        return distance <= 10.0f;
                    case "far":
                        return distance > 10.0f;
                }
                return false;
            }

            var floatValue = float.Parse(filterValue, CultureInfo.InvariantCulture.NumberFormat);
            switch (operatorToken)
            {
                case "=":
                    return distance == floatValue;
                case "!=":
                    return distance != floatValue;
                case "<":
                    return distance < floatValue;
                case "<=":
                    return distance <= floatValue;
                case ">":
                    return distance > floatValue;
                case ">=":
                    return distance >= floatValue;
            }
            return false;
        }, paramStringValue =>
            {
                // Transform the parameter from a string to a usable Vector2

                // If the user specified a vector
                if (paramStringValue.StartsWith("[") && paramStringValue.EndsWith("]"))
                {
                    paramStringValue = paramStringValue.Trim('[', ']');
                    var vectorTokens = paramStringValue.Split(',');
                    var vectorValues = vectorTokens.Select(token => float.Parse(token, CultureInfo.InvariantCulture.NumberFormat)).ToList();
                    return new Vector2(vectorValues[0], vectorValues[1]);
                }

                // Treat the value as the name of an object
                var myObj = s_Data.Find(obj => obj.name == paramStringValue);
                return myObj.position;
            });

        s_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, 10), active = true },
            new MyObjectType { id = 2, name = "Test 3", position = new Vector2(10, 0), active = false },
            new MyObjectType { id = 3, name = "Test 4", position = new Vector2(12f, 0), active = false },
        };

        // Find all items that are "near" "Test 1", including "Test 1"
        var query = queryEngine.ParseQuery("dist(Test 1):near");
        var filteredData = query.Apply(s_Data).ToList();
        Debug.Assert(filteredData.Count == 3, $"There should be 3 items in the filtered list but found {filteredData.Count} items.");
        Debug.Assert(!filteredData.Contains(s_Data[3]), "Test 4 should not be in the list as it is far of Test 1.");

        // Find all items that are far of [0, 0]
        query = queryEngine.ParseQuery("dist([0, 0]):far");
        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[3]), "Test 4 should be in the list as it is far of [0, 0].");
    }

    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 override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}


声明

public Search.IQueryEngineFilter 添加过滤器(Regex 令牌, Func<TData,string,TFilter> getDataFunc, string[] 支持的操作员类型);

声明

public Search.IQueryEngineFilter 添加过滤器(Regex 令牌, Func<TData,string,TFilter> getDataFunc, stringComparison stringComparison, string[] 支持的操作员类型);

参数

token 与过滤器匹配的正则表达式。匹配过滤器中操作符之前的内容(例如,“id>=2” 中的“id”)。
getDataFunc 用于获取过滤器中使用的对象的回调。获取一个 TData 类型的对象、一个表示已匹配的实际过滤器名称的字符串,并返回一个 TFilter 类型的对象。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。
stringComparison 字符串比较选项。

返回

IQueryEngineFilter 新过滤器。

说明

用正则表达式添加一个新的自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

使用这个重载,如果你不需要亲自处理运算符,来注册匹配正则表达式的基本过滤器。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Regex
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Regex")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });
        SetupPropertyHandlers(queryEngine);

        // Add a regular expression filter to filter generic properties
        // When adding a new regular expression filter, there needs to be a single capturing group to retrieve the
        // actual name of the filter that matched.
        queryEngine.AddFilter(new Regex("#([\\w.]+)"), (myObj, filterNameMatch) =>
        {
            if (myObj.property.name == filterNameMatch)
                return myObj.property;
            return Property.invalid;
        });

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

        // Find all objects that have a property "size" greater than 32
        var query = queryEngine.ParseQuery("#size>32");
        var filteredData = query.Apply(s_Data).ToList();
        Debug.Assert(filteredData.Count == 2, $"There should be 2 items in the filtered list but found {filteredData.Count} items.");
        Debug.Assert(filteredData.Contains(s_Data[0]), "Object 0 should be in the list as its property \"size\" is > 32.");
        Debug.Assert(filteredData.Contains(s_Data[1]), "Object 1 should be in the list as its property \"size\" is > 32.");

        // Find all objects that have a property "size" equal to 128
        query = queryEngine.ParseQuery("#size=128");
        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[1]), "Object 1 should be in the list as its property \"size\" is = 128.");

        // Find all objects that have a property "tag" that contains "item"
        query = queryEngine.ParseQuery("#tag:item");
        filteredData = query.Apply(s_Data).ToList();
        Debug.Assert(filteredData.Count == 2, $"There should be 2 items in the filtered list but found {filteredData.Count} items.");
        Debug.Assert(filteredData.Contains(s_Data[2]), "Object 2 should be in the list as its property \"tag\" contains \"item\".");
        Debug.Assert(filteredData.Contains(s_Data[3]), "Object 3 should be in the list as its property \"tag\" contains \"item\".");
    }

    static void SetupPropertyHandlers(QueryEngine<MyObjectType> qe)
    {
        qe.AddOperatorHandler(":", (Property v, int number, StringComparison sc) => PropertyIntCompare(v, number, (f, r) => f.ToString().IndexOf(r.ToString()) != -1));
        qe.AddOperatorHandler("=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f == r));
        qe.AddOperatorHandler("!=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f != r));
        qe.AddOperatorHandler("<=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f <= r));
        qe.AddOperatorHandler("<", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f < r));
        qe.AddOperatorHandler(">", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f > r));
        qe.AddOperatorHandler(">=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f >= r));
        qe.AddOperatorHandler(":", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => f.IndexOf(r, sc) != -1));
        qe.AddOperatorHandler("=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Equals(f, r, sc)));
        qe.AddOperatorHandler("!=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => !string.Equals(f, r, sc)));
        qe.AddOperatorHandler("<=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) <= 0));
        qe.AddOperatorHandler("<", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) < 0));
        qe.AddOperatorHandler(">", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) > 0));
        qe.AddOperatorHandler(">=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) >= 0));
    }

    static bool PropertyStringCompare(Property p, string s, Func<string, string, bool> comparer)
    {
        if (p.type != PropertyType.String)
            return false;
        return comparer((string)p.value, s);
    }

    static bool PropertyIntCompare(Property p, int number, Func<int, int, bool> comparer)
    {
        if (p.type != PropertyType.Integer)
            return false;
        return comparer((int)p.value, number);
    }

    enum PropertyType
    {
        None,
        Integer,
        String,
        Integer_Array
    }

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

        public static Property invalid = new Property(string.Empty, PropertyType.None, null);
    }

    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; } = Property.invalid;

        public override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,TFilter> getDataFunc, string[] supportedOperatorType);

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,TFilter> getDataFunc, stringComparison stringComparison, string[] supportedOperatorType);

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,TFilter> getDataFunc, Func<string,TParam> parameterTransformer, string[] supportedOperatorType);

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,TFilter> getDataFunc, Func<string,TParam> parameterTransformer, stringComparison stringComparison, string[] supportedOperatorType);

参数

token 与过滤器匹配的正则表达式。匹配过滤器中操作符之前的内容(例如,“id>=2” 中的“id”)。
getDataFunc 用于获取在过滤器中使用的对象的回调。获取类型为 TData 的对象,表示匹配的实际过滤器名称的字符串,类型为 TParam 的对象,并返回类型为 TFilter 的对象。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。
stringComparison 字符串比较选项。
parameterTransformer 用于将字符串转换成 TParam 类型的回调。解析查询时使用,将传递给函数的内容转换成正确的格式。

返回

IQueryEngineFilter 新过滤器。

说明

用正则表达式和参数添加一个新的自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

<TParam>:传递给过滤器的的数据类型。

使用这个重载,如果你不需要亲自处理运算符,来注册匹配正则表达式和接受参数的过滤器。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Param_Regex
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Param_Regex")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });
        SetupPropertyHandlers(queryEngine);

        // Add a regular expression filter function to filter generic properties with parameters
        // When adding a new regular expression filter, there needs to be a single capturing group to retrieve the
        // actual name of the filter that matched.
        queryEngine.AddFilter<int, Property>(new Regex("\\$([\\w.]+)"), (myObj, filterNameMatch, param) =>
        {
            if (myObj.property.name != filterNameMatch)
                return Property.invalid;
            if (myObj.property.type != PropertyType.Integer_Array)
                return Property.invalid;
            if (!(myObj.property.value is int[] array))
                return Property.invalid;
            if (param < 0 || param >= array.Length)
                return Property.invalid;
            return new Property(myObj.property.name, PropertyType.Integer, array[param]);
        });

        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 = 4, property = new Property("values", PropertyType.Integer_Array, new int[] {0, 2, 42}) },
            new MyObjectType { id = 5, property = new Property("values", PropertyType.Integer_Array, new int[] {8, 52, 210}) },
            new MyObjectType { id = 6, property = new Property("weights", PropertyType.Integer_Array, new int[] {1000, 250, 400}) }
        };

        // Find all objects that have a property "values" with a sub value greater than 42 at index 1
        var query = queryEngine.ParseQuery("$values(1)>42");
        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[5]), "Object 5 should be in the list as its property \"values\" at index 1 is > 42.");

        // Find all objects that have a property "weights" with a sub value lower or equal to 1000 at index 0
        query = queryEngine.ParseQuery("$weights(0)<=1000");
        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[6]), "Object 6 should be in the list as its property \"weights\" at index 0 is <= 1000.");
    }

    static void SetupPropertyHandlers(QueryEngine<MyObjectType> qe)
    {
        qe.AddOperatorHandler(":", (Property v, int number, StringComparison sc) => PropertyIntCompare(v, number, (f, r) => f.ToString().IndexOf(r.ToString()) != -1));
        qe.AddOperatorHandler("=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f == r));
        qe.AddOperatorHandler("!=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f != r));
        qe.AddOperatorHandler("<=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f <= r));
        qe.AddOperatorHandler("<", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f < r));
        qe.AddOperatorHandler(">", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f > r));
        qe.AddOperatorHandler(">=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f >= r));
        qe.AddOperatorHandler(":", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => f.IndexOf(r, sc) != -1));
        qe.AddOperatorHandler("=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Equals(f, r, sc)));
        qe.AddOperatorHandler("!=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => !string.Equals(f, r, sc)));
        qe.AddOperatorHandler("<=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) <= 0));
        qe.AddOperatorHandler("<", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) < 0));
        qe.AddOperatorHandler(">", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) > 0));
        qe.AddOperatorHandler(">=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) >= 0));
    }

    static bool PropertyStringCompare(Property p, string s, Func<string, string, bool> comparer)
    {
        if (p.type != PropertyType.String)
            return false;
        return comparer((string)p.value, s);
    }

    static bool PropertyIntCompare(Property p, int number, Func<int, int, bool> comparer)
    {
        if (p.type != PropertyType.Integer)
            return false;
        return comparer((int)p.value, number);
    }

    enum PropertyType
    {
        None,
        Integer,
        String,
        Integer_Array
    }

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

        public static Property invalid = new Property(string.Empty, PropertyType.None, null);
    }

    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; } = Property.invalid;

        public override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,string,TFilter,bool> filterResolver, string[] supportedOperatorType);

参数

token 与过滤器匹配的正则表达式。匹配过滤器中操作符之前的内容(例如,“id>=2” 中的“id”)。
filterResolver 用于处理该过滤器的任何运算符的回调。获取类型为 TData 的对象,表示匹配的实际过滤器名称的字符串,运算符令牌和过滤器值,并返回一个布尔值,表示过滤器是否通过。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。

返回

IQueryEngineFilter 新过滤器。

说明

用正则表达式和一个完整的解析器添加一个新的自定义过滤器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

使用这个重载,如果你需要亲自处理运算符,来注册匹配正则表达式的基本过滤器。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Resolver_Regex
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Resolver_Regex")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });
        SetupPropertyHandlers(queryEngine);

        // Add a regular expression filter to filter generic properties, with a resolver to handle all operators yourself.
        // When adding a new regular expression filter, there needs to be a single capturing group to retrieve the
        // actual name of the filter that matched.
        queryEngine.AddFilter<string>(new Regex("p_([\\w]+)"), (myObj, filterNameMatch, operatorToken, filterValue) =>
        {
            if (operatorToken != ":")
                return false;
            if (myObj.property.name != filterNameMatch)
                return false;

            switch (filterValue)
            {
                case "enabled":
                    return myObj.property.enabled;
                case "empty":
                    {
                        if (myObj.property.type != PropertyType.Integer_Array)
                            return false;
                        if (!(myObj.property.value is int[] array))
                            return false;
                        return array.Length == 0;
                    }
                default: return false;
            }
        }, new[] {":"});

        s_Data = new List<MyObjectType>()
        {
            new MyObjectType { id = 0, property = new Property("size", PropertyType.Integer, 64, true) },
            new MyObjectType { id = 1, property = new Property("size", PropertyType.Integer, 128, false) },
            new MyObjectType { id = 2, property = new Property("tag", PropertyType.String, "item", true) },
            new MyObjectType { id = 3, property = new Property("tag", PropertyType.String, "car item", false) },
            new MyObjectType { id = 4, property = new Property("values", PropertyType.Integer_Array, new int[] {0, 2, 42}, true) },
            new MyObjectType { id = 5, property = new Property("values", PropertyType.Integer_Array, new int[] {8, 52, 210}, false) },
            new MyObjectType { id = 6, property = new Property("weights", PropertyType.Integer_Array, new int[] {1000, 250, 400}, false) },
            new MyObjectType { id = 7, property = new Property("weights", PropertyType.Integer_Array, new int[] {}, false) }
        };

        // Find all items that have a property "size" that is enabled.
        var query = queryEngine.ParseQuery("p_size:enabled");
        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]), "Object 0 should be in the list as its property \"size\" is enabled.");

        // Find all items that have a property "weights" that is empty.
        query = queryEngine.ParseQuery("p_weights:empty");
        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[7]), "Object 7 should be in the list as its property \"weights\" is empty.");
    }

    static void SetupPropertyHandlers(QueryEngine<MyObjectType> qe)
    {
        qe.AddOperatorHandler(":", (Property v, int number, StringComparison sc) => PropertyIntCompare(v, number, (f, r) => f.ToString().IndexOf(r.ToString()) != -1));
        qe.AddOperatorHandler("=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f == r));
        qe.AddOperatorHandler("!=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f != r));
        qe.AddOperatorHandler("<=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f <= r));
        qe.AddOperatorHandler("<", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f < r));
        qe.AddOperatorHandler(">", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f > r));
        qe.AddOperatorHandler(">=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f >= r));
        qe.AddOperatorHandler(":", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => f.IndexOf(r, sc) != -1));
        qe.AddOperatorHandler("=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Equals(f, r, sc)));
        qe.AddOperatorHandler("!=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => !string.Equals(f, r, sc)));
        qe.AddOperatorHandler("<=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) <= 0));
        qe.AddOperatorHandler("<", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) < 0));
        qe.AddOperatorHandler(">", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) > 0));
        qe.AddOperatorHandler(">=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) >= 0));
    }

    static bool PropertyStringCompare(Property p, string s, Func<string, string, bool> comparer)
    {
        if (p.type != PropertyType.String)
            return false;
        return comparer((string)p.value, s);
    }

    static bool PropertyIntCompare(Property p, int number, Func<int, int, bool> comparer)
    {
        if (p.type != PropertyType.Integer)
            return false;
        return comparer((int)p.value, number);
    }

    enum PropertyType
    {
        None,
        Integer,
        String,
        Integer_Array
    }

    struct Property
    {
        public string name { get; }
        public PropertyType type { get; }
        public object value { get; set; }
        public bool enabled { get; set; }

        public Property(string name, PropertyType type, object value, bool enabled)
        {
            this.name = name;
            this.type = type;
            this.value = value;
            this.enabled = enabled;
        }

        public static Property invalid = new Property(string.Empty, PropertyType.None, null, false);
    }

    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; } = Property.invalid;

        public override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,string,TFilter,bool> filterResolver, string[] supportedOperatorType);

声明

public Search.IQueryEngineFilter AddFilter(Regex token, Func<TData,string,TParam,string,TFilter,bool> filterResolver, Func<string,TParam> parameterTransformer, string[] supportedOperatorType);

参数

token 与过滤器匹配的正则表达式。匹配过滤器中操作符之前的内容(例如,“id>=2” 中的“id”)。
filterResolver 用于处理此筛选器的任何运算符的回调。获取 TData 类型的对象、表示已匹配的实际筛选器名称的字符串、TParam 类型的对象、运算符令牌和筛选器值,并返回一个布尔值,指示筛选器是否通过。
supportedOperatorType 受支持的操作符令牌列表。此列表包含受支持的操作符令牌。将 null 或空列表与指示支持所有运算符相关联。
parameterTransformer 用于将字符串转换成 TParam 类型的回调。解析查询时使用,将传递给函数的内容转换成正确的格式。

返回

IQueryEngineFilter 新过滤器。

说明

使用正则表达式、参数和完整解析器添加新的自定义筛选器。

<TData>:QueryEngine 筛选的数据类型。

<TFilter>:筛选器比较的数据类型。

<TParam>:传递给过滤器的的数据类型。

如果您需要自己处理运算符,则可以使用此重载来注册与正则表达式匹配并接受参数的筛选器。

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Search;
using UnityEngine;

static class Example_QueryEngine_AddFilter_Param_Resolver_Regex
{
    static List<MyObjectType> s_Data;

    [MenuItem("Examples/QueryEngine/AddFilter_Param_Resolver_Regex")]
    public static void RunExample()
    {
        // Set up the query engine
        var queryEngine = new QueryEngine<MyObjectType>();
        queryEngine.SetSearchDataCallback(myObj => new[] { myObj.id.ToString(), myObj.name });

        // Add a regular expression filter to filter generic properties, with a resolver to handle all operators yourself.
        // When adding a new regular expression filter, there needs to be a single capturing group to retrieve the
        // actual name of the filter that matched.
        queryEngine.AddFilter<int, string>(new Regex("p_([\\w]+)"), (myObj, filterNameMatch, index, operatorToken, filterValue) =>
        {
            if (myObj.property.name != filterNameMatch)
                return false;
            if (myObj.property.type != PropertyType.Integer_Array)
                return false;
            if (!(myObj.property.value is int[] array))
                return false;

            if (operatorToken == ":")
            {
                switch (filterValue)
                {
                    case "valid":
                        return index >= 0 && index < array.Length;
                    default: return false;
                }
            }

            if (index < 0 || index >= array.Length)
                return false;

            var value = array[index];
            var integerValue = int.Parse(filterValue, CultureInfo.InvariantCulture.NumberFormat);
            switch (operatorToken)
            {
                case "=":
                    return value == integerValue;
                case "!=":
                    return value != integerValue;
                case "<":
                    return value < integerValue;
                case "<=":
                    return value <= integerValue;
                case ">":
                    return value > integerValue;
                case ">=":
                    return value >= integerValue;
            }
            return false;
        });

        s_Data = new List<MyObjectType>()
        {
            new MyObjectType { id = 0, property = new Property("size", PropertyType.Integer, 64, true) },
            new MyObjectType { id = 1, property = new Property("size", PropertyType.Integer, 128, false) },
            new MyObjectType { id = 2, property = new Property("tag", PropertyType.String, "item", true) },
            new MyObjectType { id = 3, property = new Property("tag", PropertyType.String, "car item", false) },
            new MyObjectType { id = 4, property = new Property("values", PropertyType.Integer_Array, new int[] {0, 2, 42}, true) },
            new MyObjectType { id = 5, property = new Property("values", PropertyType.Integer_Array, new int[] {8, 52, 210}, false) },
            new MyObjectType { id = 6, property = new Property("weights", PropertyType.Integer_Array, new int[] {1000, 250, 400}, false) },
            new MyObjectType { id = 7, property = new Property("weights", PropertyType.Integer_Array, new int[] {}, false) }
        };

        // Find all items that have a property named "weights" with a valid value at index 2.
        var query = queryEngine.ParseQuery("p_weights(2):valid");
        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[6]), "Object 6 should be in the list as its property \"weights\" has a valid value at index 2.");

        // Find all items that have a property named "values" with a value greater than 50 at index 1.
        query = queryEngine.ParseQuery("p_values(1)>50");
        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[5]), "Object 5 should be in the list as its property \"values\" has a value > 50 at index 1.");
    }

    static void SetupPropertyHandlers(QueryEngine<MyObjectType> qe)
    {
        qe.AddOperatorHandler(":", (Property v, int number, StringComparison sc) => PropertyIntCompare(v, number, (f, r) => f.ToString().IndexOf(r.ToString()) != -1));
        qe.AddOperatorHandler("=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f == r));
        qe.AddOperatorHandler("!=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f != r));
        qe.AddOperatorHandler("<=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f <= r));
        qe.AddOperatorHandler("<", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f < r));
        qe.AddOperatorHandler(">", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f > r));
        qe.AddOperatorHandler(">=", (Property v, int number) => PropertyIntCompare(v, number, (f, r) => f >= r));
        qe.AddOperatorHandler(":", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => f.IndexOf(r, sc) != -1));
        qe.AddOperatorHandler("=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Equals(f, r, sc)));
        qe.AddOperatorHandler("!=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => !string.Equals(f, r, sc)));
        qe.AddOperatorHandler("<=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) <= 0));
        qe.AddOperatorHandler("<", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) < 0));
        qe.AddOperatorHandler(">", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) > 0));
        qe.AddOperatorHandler(">=", (Property v, string s, StringComparison sc) => PropertyStringCompare(v, s, (f, r) => string.Compare(f, r, sc) >= 0));
    }

    static bool PropertyStringCompare(Property p, string s, Func<string, string, bool> comparer)
    {
        if (p.type != PropertyType.String)
            return false;
        return comparer((string)p.value, s);
    }

    static bool PropertyIntCompare(Property p, int number, Func<int, int, bool> comparer)
    {
        if (p.type != PropertyType.Integer)
            return false;
        return comparer((int)p.value, number);
    }

    enum PropertyType
    {
        None,
        Integer,
        String,
        Integer_Array
    }

    struct Property
    {
        public string name { get; }
        public PropertyType type { get; }
        public object value { get; set; }
        public bool enabled { get; set; }

        public Property(string name, PropertyType type, object value, bool enabled)
        {
            this.name = name;
            this.type = type;
            this.value = value;
            this.enabled = enabled;
        }

        public static Property invalid = new Property(string.Empty, PropertyType.None, null, false);
    }

    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; } = Property.invalid;

        public override string ToString()
        {
            return $"({id}, {name}, ({position.x}, {position.y}), {active})";
        }
    }
}