How to change terms in an Expression?

3

Based on the following response in: How to convert an expression tree to a partial SQL query? , I'm using a class inherited from ExpressionVisitor to try to treat some conditions in my expressions.

Example usage:

var pessoaId = 1; // dessa variável preciso trocar na expressão por parâmetro 
                  // e retornar no dicionario o nome do parâmetro e valor do mesmo.

var expression = ((pessoa, telefones) => pessoa.Id == pessoaId);

var queryFilterParser = new QueryFilterParser();
var paramValues = queryFilterParser.Parse(expression);

And for this I have:

public class QueryFilterParser : ExpressionVisitor
{
    public Dictionary<string, object> ParamValues { get; private set; }
    ...
    protected override Expression VisitConstant(ConstantExpression constantExpression)
    {
        // Em: (pessoa.Id == value(GenericDAO.Tests.DAOTests+<>c__DisplayClass0).pessoaId)
        // trocar value(GenericDAO.Tests.DAOTests+<>c__DisplayClass0).pessoaId por
        // @pessoaId

        // obter o valor e saber o nome do parâmetro para alimentar o dicionário
        return base.VisitConstant(constantExpression);
    }
    ...
}

I need to return a dictionary containing the name of a parameter and its value for Dictionary<string, object> . Then it is necessary to change the term inside the expression, leaving a string in the format of an SQL parameter and get the value of ConstantExpression .

How can this be done?

Issue:

To get the value and name of the parameter I'm doing the following in the VisitMember method:

protected override Expression VisitMember(MemberExpression memberExpression)
{
    ...
    else if (memberExpression.Expression.NodeType == ExpressionType.Constant)
    {
        var name = memberExpression.Member.Name;
        var constantExpression = (ConstantExpression)memberExpression.Expression;
        var value = (memberExpression.Member as FieldInfo).GetValue(constantExpression.Value);

        ParamValues.Add(name, value);

        this.Visit(constantExpression);
        return memberExpression;
    }
    ...
}

The constant within the expression is now replaced by the parameter name. How to do it?

Issue 2:

Apparently this response from Jon Skeet solves the problem, but with me it did not work: How to get the value of ConstantExpression which uses local variable? .

As far as I understand, return Expression.Constant("@" + name, typeof(string)); should work.

A simple expression containing {@pessoaId} is generated but is not returned as in the example that it gave the term changed.

protected override Expression VisitMember(MemberExpression memberExpression)
{
    ...
    else if (memberExpression.Expression.NodeType == ExpressionType.Constant)
    {
        var name = memberExpression.Member.Name;
        var constantExpression = (ConstantExpression)memberExpression.Expression;
        var value = (memberExpression.Member as FieldInfo).GetValue(constantExpression.Value);

        ParamValues.Add(name, value);

        // pelo exemplo de Jon Skeet isso resolveria ...
        return Expression.Constant("@" + name, typeof(string)); 
    }
    ...
}

How can this be done?

    
asked by anonymous 22.11.2014 / 14:32

1 answer

2

The process becomes much simpler if the SQL statement constructor is based on ExpressionVisitor , as in DefaultSqlQueryGenerator of EF 7 , and that followed by Jon Skeet in your response in How to convert an expression to a partial SQL query? .

In this strategy the complications have disappeared.

About

  

the original expression becomes something like (pessoa, telefones) => pessoa.Id == "@pessoaId"

It is not possible because an expression is immutable so it is not possible to change its members as I wanted. What I could do is create a new expression to return, but treat this in all Visitors methods.

But as stated in question 2, actually Expression.Constant("@" + name, typeof(string)) returns "@Name" .

    
24.11.2014 / 14:18