为不同类型的嵌套属性创建递归Regex.IsMatch表达式< Func< T,bool>>

xzv2uavs  于 2023-11-20  发布在  其他
关注(0)|答案(2)|浏览(160)

我有一个基于Regex创建Expression的方法,它可以很好地处理相关实体的直接属性。

public static Expression<Func<T, bool>> CreateRegExExpression<T>(string pattern, string property)
{
        var paramObject = Expression.Parameter(typeof(T));
        var paramType = Expression.TypeAs(paramObject, typeof(T));
        var propertyField = Expression.Property(paramType, property);

        var _pattern = Expression.Constant(pattern, typeof(string));
        var paramsEx = new Expression[] { propertyField, _pattern };

        var methodInfo = typeof(Regex).GetMethod("IsMatch", new Type[] { typeof(string), typeof(string) });
        if (!methodInfo.IsStatic || methodInfo == null)
            throw new NotSupportedException();
        
        var lamdaBody = Expression.Call(null, methodInfo, paramsEx);
        return Expression.Lambda<Func<T, bool>>(lamdaBody, paramObject);
}

字符串
然而,我还不能使这一工作的嵌套属性,如entity.sub_entity.property作为调用CreateRegExExpression需要<T>类适当地返回lamba?
有没有人得到任何提示,如何动态地为嵌套的属性构造lambda,因为下面的工作很好,但我似乎不能解决如何使用上面的函数递归。

Expression<Func<entity, bool>> lambda = e => Regex.Ismatch(e.sub_entity.property, pattern)

vaqhlq81

vaqhlq811#

如果我正确理解了你的问题,你可以允许传递“路径”而不仅仅是属性名,然后拆分并重新命名:

static Expression<Func<T, bool>> CreateRegExExpression<T>(string pattern, string property)
{
    var paramObject = Expression.Parameter(typeof(T));
    var paramType = Expression.TypeAs(paramObject, typeof(T));
    var props = property.Split(".");
    Expression propertyField = Expression.Property(paramType, props[0]);

    foreach (var prop in props.Skip(1))
    {
        propertyField = Expression.Property(propertyField, prop);
    }

    var _pattern = Expression.Constant(pattern, typeof(string));
    var paramsEx = new Expression[] { propertyField, _pattern };

    var methodInfo = typeof(Regex).GetMethod("IsMatch", new Type[] { typeof(string), typeof(string) });
    if (!methodInfo.IsStatic || methodInfo == null)
        throw new NotSupportedException();
        
    var lamdaBody = Expression.Call(null, methodInfo, paramsEx);
    return Expression.Lambda<Func<T, bool>>(lamdaBody, paramObject);
}

字符串
例如CreateRegExExpression(pattern, "sub_entity.property")
或者,如果你没有完整的路径,只有“前一个”属性表达式,你可以使用反射来调用方法:

var memberReflectedType = previousPropertyField.Member.ReflectedType;
var propFieldType = previousPropertyField.Type;
var makeGenericMethod = typeof(CreateRegExExpressionHolder).GetMethod(nameof(CreateRegExExpression), BindingFlags.Public | BindingFlags.Static)
    .MakeGenericMethod(propFieldType);
var invoke = makeGenericMethod.Invoke(null, new[] { pattern, finalPropName }) as Expression;

jogvjijk

jogvjijk2#

除了古鲁的回答。
你可以在SharpLab或LinqPad上看看C#编译器是如何为你的代码Expression<Func<entity, bool>> lambda = e => Regex.IsMatch(e.sub_entity.property, pattern)推断它的:


的数据

相关问题