How to exchange terms in an Expression?

Asked

Viewed 92 times

3

Based on the following reply 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 of use:

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 that 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 to the Dictionary<string, object>. Then it is necessary to swap 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?


Editing:

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

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

Missing now replace the Constant within the expression by the parameter name. How to do ?


Issue 2:

Apparently this answer from Jon Skeet solves the problem, but with me it didn’t work: How to get the value of a Constantexpression which uses a local variable?.

From what 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 he 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?

  • Expression.Constant it serves to store a constant value. The substitution made in its edition makes the original expression translate into something like (pessoa, telefones) => pessoa.Id == "@pessoaId".

1 answer

2

The process becomes much simpler if the SQL command builder is based on ExpressionVisitor, as in Defaultsqlquerygenerator of EPH 7, and which follows the one presented by Jon Skeet in his reply in How to Convert an Expression Tree to a partial SQL query?.

In this strategy the complications disappeared.

About

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

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

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.