Expresión.Al igual que en C #

c# expression-trees sql-like

Pregunta

por ejemplo: x => x.Name = "g"

Tengo bloque de código como este

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

Funciona como el encanto pero necesito Expression.Like (como "g" no es igual a "g")

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

pero el árbol de expresiones C # no admite el método Like

ACTUALIZACIÓN :

Escribí algo como esto:

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

pero necesito BinaryExpression no MethodCallExpression

Respuesta aceptada

Puede hacer que su código funcione agregando una expresión igual sobre la llamada al método, de esta manera:

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

En el pseudo código esto se lee como:

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

Lo que te devolverá una expresión binaria.


Respuesta popular

He hecho esto en un lenguaje de scripting que escribí, lo que te permite decir cosas como name like 'bob%' . El truco es que necesita asignarlo a una llamada de método que tome el valor y la expresión regular y llamar a esto desde dentro de la Expression .

Si echas un vistazo a la clase LikeEvaluator en mi lenguaje de scripts Wire , verás cómo lo hice:

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


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow