Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement expression Directory Tree Expression in C #

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is about how to implement the expression directory tree Expression in C #. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Expression directory tree

Expression directory tree: syntax tree, or a data structure

1. Expression directory tree Expression:System.Linq.Expressions

two。 Describe the relationship between multiple variables or constants and assemble them according to certain rules!

You can use the same lambd expression shortcut declaration as a delegate

There can be no statement style, and the declaration can only have one line of code.

Can be compiled into a delegate through Compile ()

Func func = (m, n) = > {int I = 0; return m * n + 2;}; / / the delegated Ramda expression is actually a parameter of the delegate, essentially a method (anonymous method) Expression exp = (m, n) = > m * n + 2 / / data structure-just like a precise description of a calculation, after expansion, it is found that the value can be obtained for each element, left and right, and the binary tree var erpPlu= exp.Compile (); / / the expression directory tree can be transformed into a delegate / / expression directory tree through compile: syntax tree, or a data structure int iResult1 = func.Invoke (12,23). Int iResult2 = exp.Compile () .Invoke (12,23)

The assembly of expression directory tree

Manually assemble the expression directory tree, not a shortcut to lambda

/ / the assembly of the expression directory tree Expression expression = () = > 123 + 234; / / the addition of two constants-the shortcut declaration of the expression directory tree Expression constant123 = Expression.Constant; Expression constant234 = Expression.Constant; Expression expressionAdd = Expression.Add (constant123, constant234); var exp = Expression.Lambda (expressionAdd); var func = exp.Compile (); int iResult = func.Invoke (); Expression exp = (m, n) = > m * n + m + n + 2 / / Shortcut declaration-in fact, the convenient function provided by the compiler-Syntax Sugar-specific implementation can be viewed through decompilation tool ParameterExpression parameterExpression = Expression.Parameter (typeof (int), "m"); ParameterExpression parameterExpression2 = Expression.Parameter (typeof (int), "n"); Expression expContant2 = Expression.Constant (2, typeof (int)); Expression multipley = Expression.Multiply (parameterExpression, parameterExpression2) Expression expAdd = Expression.Add (multipley, parameterExpression); Expression expAdd1 = Expression.Add (expAdd, parameterExpression2); Expression expAdd2 = Expression.Add (expAdd1, expContant2); Expression expression = Expression.Lambda (expAdd2, new ParameterExpression [] {parameterExpression,parameterExpression2}); Func fun = expression.Compile (); int iResult = fun.Invoke (10,11); var peopleQuery = new List () AsQueryable (); Expression lambda = x = > x.Id.ToString (). Equals ("5"); peopleQuery.Where (lambda) ParameterExpression parameterExpression = Expression.Parameter (typeof (People), "x"); FieldInfo idfield = typeof (People) .GetField ("Id"); var idExp = Expression.Field (parameterExpression, idfield); MethodInfo toString = typeof (int) .GetMethod ("ToString", new Type [0]); var toStringExp = Expression.Call (idExp, toString, Array.Empty ()); var Equals = typeof (string) .GetMethod ("Equals", new Type [] {typeof (string)}); Expression expressionConstant5 = Expression.Constant ("5", typeof (string)) Var equalsExp = Expression.Call (toStringExp, Equals, new Expression [] {expressionConstant5}); Expression expression = Expression.Lambda (equalsExp, new ParameterExpression [] {parameterExpression}); Func func = expression.Compile (); var bResult = func.Invoke (new People () {Id = 5, Name = "seashells"}); new List (). AsQueryable (). Where (expression); Application Linq to SQLvar dbSet = new List (). AsQueryable () / / EF DbSet dbSet.Where (p = > p.Age = = 25 & p.Name.Contains ("smile in the sun"); Expression exp = null;Console.WriteLine ("user enters a name, skip if empty"); string name = Console.ReadLine (); if (! string.IsNullOrWhiteSpace (name)) {exp = p = > p.Name.Contains (name);} Console.WriteLine ("enter a minimum age, skip if empty"); string age = Console.ReadLine () If (! string.IsNullOrWhiteSpace (age) & & int.TryParse (age, out int iAge)) {exp = p = > p.Age > iAge;}

Is it true that only the last condition is effective in the above play? What if multiple conditions need to be met? Assembling, of course.

Assembling can assemble the expression directory tree from the minimum granularity; if there is an encapsulation, you give me various conditions, and I will assemble one by one from the minimum granularity, isn't it a long expression directory tree?

Solution:

The caller can assemble a long expression directory tree and pass it to it.

What should I do here after the expression directory tree is passed? Should be parsed

All the information is in the expression directory tree, and it can be parsed (found out).

Parsing can be done through ExpressionVisitor parsing-generating corresponding Sql statements.

ExpressionVisitor

Visitors to the expression directory tree-Visitor pattern

1.Visit method-access the entry to the expression directory tree-identify what type of expression directory it is

two。 Schedule further access to a more professional method, and after the visit, a new expression directory is generated-a bit like recursion, not all recursive

3. Because the expression directory tree is a binary tree, ExpressionVisitor goes all the way down to the leaf node; that accesses all the nodes

4. In any link of the visit, you can get the content corresponding to the current link (parameter name, parameter value.) Can be further expanded

Why use the expression directory tree to assemble parsing:

1. Can improve reusability

two。 If you encapsulate a method and accept an expression directory tree, when parsing, it is actually constantly accessing, and the access is regular.

3. Any expression directory tree can call the current method to parse

4. Expression directory trees can support generics

{Expression lambda = x = > x.Age > 5 & & x.Id > 5 & & x.Name.StartsWith ("1") / / like'1%'& & x.Name.EndsWith ("1") / / Like'1' & & x.Name.Contains ("1") / / like'% 1%'/ / string sql = string.Format ("Delete From [{0}] WHERE [Age] > 5 AND [ID] > 5", typeof (People) .Name, "[Age] > 5 AND [ID] > 5"); ConditionBuilderVisitor vistor = new ConditionBuilderVisitor (); vistor.Visit (lambda) Console.WriteLine (vistor.Condition ());} {/ / ([Age] >'5') AND ([Name] = [name]) OR ([Id] >'5') string name = "AAA"; Expression lambda = x = > x.Age > 5 & & x.Name = = name | | x.Id > 5 ConditionBuilderVisitor vistor = new ConditionBuilderVisitor (); vistor.Visit (lambda); Console.WriteLine (vistor.Condition ());} {Expression lambda = x = > x.Age > 5 | (x.Name = = "A" & & x.Id > 5); ConditionBuilderVisitor vistor = new ConditionBuilderVisitor (); vistor.Visit (lambda) Console.WriteLine (vistor.Condition ()); {Expression lambda = x = > (x.Age > 5 | | x.Name = = "A") & & x.Id > 5; ConditionBuilderVisitor vistor = new ConditionBuilderVisitor (); vistor.Visit (lambda); Console.WriteLine (vistor.Condition ());}

Self-encapsulated parser, which is the underlying principle of EF6, automatically generates corresponding sql statements according to the expression tree.

Public class ConditionBuilderVisitor: ExpressionVisitor {private Stack _ StringStack = new Stack (); public string Condition () {string condition = string.Concat (this._StringStack.ToArray ()); this._StringStack.Clear (); return condition } / if it is a binary expression / protected override Expression VisitBinary (BinaryExpression node) {if (node = = null) throw new ArgumentNullException ("BinaryExpression"); this._StringStack.Push (")"); base.Visit (node.Right) / / parse right this._StringStack.Push ("" + node.NodeType.ToSqlOperator () + "); base.Visit (node.Left); / / parse left this._StringStack.Push (" ("); return node } / parse attributes / protected override Expression VisitMember (MemberExpression node) {if (node = = null) throw new ArgumentNullException ("MemberExpression"); / / this._StringStack.Push ("[" + node.Member.Name + "]"); return node If (node.Expression is ConstantExpression) {var value1 = this.InvokeValue (node); var value2 = this.ReflectionValue (node); / / this.ConditionStack.Push ($"{value1}'"); this._StringStack.Push ("" + value2 + "") } else {this._StringStack.Push ("[" + node.Member.Name + "]");} return node;} private object InvokeValue (MemberExpression member) {var objExp = Expression.Convert (member, typeof (object)) / / struct requires return Expression.Lambda (objExp). Compile (). Invoke ();} private object ReflectionValue (MemberExpression member) {var obj = (member.Expression as ConstantExpression) .value; return (member.Member as FieldInfo) .GetValue (obj) } / constant expression / protected override Expression VisitConstant (ConstantExpression node) {if (node = = null) throw new ArgumentNullException ("ConstantExpression"); this._StringStack.Push ("'" + node.Value + ""); return node Method expression / protected override Expression VisitMethodCall (MethodCallExpression m) {if (m = = null) throw new ArgumentNullException ("MethodCallExpression"); string format Switch (m.Method.Name) {case "StartsWith": format = "({0} LIKE {1} +'%')"; break; case "Contains": format = "({0} LIKE'%'+ {1} +'%')"; break Case "EndsWith": format = "({0} LIKE'%'+ {1})"; break; default: throw new NotSupportedException (m.NodeType + "is not supported!");} this.Visit (m.Object); this.Visit (m.Arguments [0]) String right = this._StringStack.Pop (); string left = this._StringStack.Pop (); this._StringStack.Push (String.Format (format, left, right)); return m }} internal static class SqlOperator {internal static string ToSqlOperator (this ExpressionType type) {switch (type) {case (ExpressionType.AndAlso): case (ExpressionType.And): return "AND" Case (ExpressionType.OrElse): case (ExpressionType.Or): return "OR"; case (ExpressionType.Not): return "NOT"; case (ExpressionType.NotEqual): return ""; case ExpressionType.GreaterThan: return ">" Case ExpressionType.GreaterThanOrEqual: return "> ="; case ExpressionType.LessThan: return "

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report