GetString Expression Tree Result

I am trying to copy the behavior of the Entity Framework when creating a query from an expression, and I found a way to use ExpressionVisitor when getting a model property using Attribute

this is what i got so far

internal class NVisitor : ExpressionVisitor { private readonly ParameterExpression _parameter; private readonly Type _type; public NVisitor(Type type) { _type = type; _parameter = Expression.Parameter(type); } protected override Expression VisitParameter(ParameterExpression node) { return _parameter; } protected override Expression VisitMember(MemberExpression node) { if (node.Member.MemberType == MemberTypes.Property) { var memberName = node.Member.Name; PropertyInfo otherMember = _type.GetProperty(memberName); var ncols = node.Member.GetCustomAttributes(typeof(NColumn), true); if (ncols.Any()) { var ncol = (NColumn)ncols.First(); otherMember = _type.GetProperty(ncol.Name); } var inner = Visit(node.Expression); return Expression.Property(inner, otherMember); } return base.VisitMember(node); } } 

I have an NColumn attribute that indicates the real name of the property from a table column, so I mark the model property by attribute

  public class BonusTypeX { [NColumn("BonusTypeName")] public string Name { get; set; } } 

now when im trying to get expression

  [TestMethod] public void ExpressionTesting2() { string searchKey = "Xmas"; Expression<Func<BonusTypeX, bool>> expression = x => x.Name.Contains(searchKey); Type t = typeof(tbl_BonusType); var body = new NVisitor(t).Visit(expression.Body); string a = string.Join(".", body.ToString().Split('.').Skip(1)); Assert.AreEqual("BonusTypeName.Contains(\"Xmas\")", a); } 

I got it

BonusTypeName.Contains (value (Payroll.Test.Administration.TestRepositories + <> c__DisplayClass13) .searchKey)

what i expect to get

BonusTypeName.Contains ("Christmas")

is there any method that gets an expression string? I use

 string a = string.Join(".", body.ToString().Split('.').Skip(1)); 

which, I think, may be wrong .. :)

Any help would be appreciated.

+6
source share
1 answer

The local variable is fixed in the class generated by the compiler at runtime, which explains the Payroll.Test.Administration.TestRepositories+<>c__DisplayClass13).searchKey . To get the generated field value in an expression, you must explicitly replace it when you visit the expression:

 protected override Expression VisitMember(MemberExpression node) { if (node.Member.MemberType == MemberTypes.Property) { var memberName = node.Member.Name; PropertyInfo otherMember = _type.GetProperty(memberName); var ncols = node.Member.GetCustomAttributes(typeof(NColumn), true); if (ncols.Any()) { var ncol = (NColumn)ncols.First(); otherMember = _type.GetProperty(ncol.Name); } var inner = Visit(node.Expression); return Expression.Property(inner, otherMember); } if (node.Member.MemberType == MemberTypes.Field) { if (node.Expression is ConstantExpression) { var owner = ((ConstantExpression)node.Expression).Value; var value = Expression.Constant(((FieldInfo)node.Member).GetValue(owner)); return value; } } return base.VisitMember(node); } 
+5
source

Source: https://habr.com/ru/post/977013/


All Articles