Expression.Comme en C #

c# expression-trees sql-like

Question

par exemple: x => x.Name = "g"

J'ai un bloc de code comme ça

public Expression<Func<TEntity, bool>> SearchExpression()
{
    var c = new ConstantExpression[_paramList.Count];
    var b = new BinaryExpression[_paramList.Count];
    BinaryExpression comparisonExpression = null;

    var entity = Expression.Parameter(typeof(TEntity));

    for (int i = 0; i < _paramList.Count; i++)
    {
        var value = Convert.ChangeType(_paramList[i].Item2 /*"g"*/, _paramList[i].Item3 /*System.String*/);
        c[i] = Expression.Constant(value); //"g"

        // PROBLEM IS HERE
        b[i] = Expression.Equal(Expression.Property(entity, _paramList[i].Item1 /*Name*/, c[i]);
        // PROBLEM IS HERE



    }
    _paramList.Clear();
    comparisonExpression = b.Aggregate(Expression.And);
    return Expression.Lambda<Func<TEntity, bool>>(comparisonExpression, entity);
}

fonctionne comme un charme , mais je dois Expression.Like (comme « g » « g » non égal)

Expression.Like(Expression.Property(entity, _paramList[i].Item1), c[i])

mais l'arbre d'expression C # ne supporte pas la méthode Like

MISE À JOUR :

J'ai écrit quelque chose comme ça:

Expression.Call(Expression.Property(entity, _paramList[i].Item1),
                typeof(String).GetMethod("Contains"), new Expression[] { c[i] });  

mais j'ai besoin de BinaryExpression et non de MethodCallExpression

Réponse acceptée

Vous pouvez faire fonctionner votre code en ajoutant une expression equals sur l'appel de la méthode, comme suit:

    b[i] = Expression.Equal(
        Expression.Call(Expression.Property(entity, _paramList[i].Item1),
        typeof (String).GetMethod("Contains"), 
          new Expression[] {c[i]}), Expression.Constant(true));

En pseudo-code, cela se lit comme suit:

b[i] = entity => entity.someProperty.Contains(c[i]) == true;

Ce qui retournera une expression binaire pour vous.


Réponse populaire

Je l'ai fait dans un langage de script que j'ai écrit, ce qui vous permet de dire des choses comme des name like 'bob%' . L'astuce consiste à mapper cette action sur un appel de méthode qui prend la valeur et l'expression régulière et appelle cette opération depuis Expression

Si vous regardez la classe LikeEvaluator dans mon langage de script Wire , vous verrez comment je l’ai fait:

static class LikeEvaluator
{
    private static readonly MethodInfo ApplyLikeMethodInfo=typeof(LikeEvaluator).GetMethod("ApplyLike");
    private static readonly MethodInfo ApplyLikeNoCaseMethodInfo=typeof(LikeEvaluator).GetMethod("ApplyLikeNoCase");

    public static Expression Like(CaseMode caseMode, Expression lhs, Expression pattern)
    {
        Expression x=null;

        if(caseMode==CaseMode.Sensitive)
        {
            x=Expression.Call(ApplyLikeMethodInfo,lhs,pattern);
        }
        else
        {
            x=Expression.Call(ApplyLikeNoCaseMethodInfo,lhs,pattern);
        }

        return x;
    }

    public static bool ApplyLike(string text, string likePattern)
    {
        string pattern=PatternToRegex(likePattern);
        return Regex.IsMatch(text,pattern,RegexOptions.None);
    }

    public static bool ApplyLikeNoCase(string text, string likePattern)
    {
        string pattern=PatternToRegex(likePattern);
        return Regex.IsMatch(text,pattern,RegexOptions.IgnoreCase);
    }

    public static string PatternToRegex(string pattern)
    {
        pattern=Regex.Escape(pattern);
        pattern=pattern.Replace("%",@".*");
        pattern=string.Format("^{0}$",pattern);

        return pattern;
    }
}


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow