Espressione.Come in C #

c# expression-trees sql-like

Domanda

ad esempio: x => x.Name = "g"

Ho un blocco di codice come questo

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

funziona come fascino ma ho bisogno di Expression.Like (come "g" non uguale a "g")

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

ma l'albero delle espressioni C # non supporta il metodo Like

AGGIORNAMENTO :

Ho scritto qualcosa del genere:

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

ma ho bisogno di BinaryExpression non MethodCallExpression

Risposta accettata

Puoi far funzionare il tuo codice aggiungendo un'espressione uguale alla chiamata al metodo, in questo modo:

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

In pseudo codice questo si legge come:

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

Quale restituirà un'espressione binaria per te.


Risposta popolare

L'ho fatto in un linguaggio di scripting che ho scritto, che ti permette di dire cose come name like 'bob%' . Il trucco è che devi associarlo a una chiamata al metodo che prende il valore e l'espressione regolare e chiama questo all'interno Expression .

Se dai un'occhiata alla classe LikeEvaluator nel mio linguaggio di script Wire vedrai come l'ho fatto:

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


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché