干货表达式树解析框架3Word格式.docx

上传人:b****4 文档编号:17267697 上传时间:2022-11-30 格式:DOCX 页数:20 大小:72.72KB
下载 相关 举报
干货表达式树解析框架3Word格式.docx_第1页
第1页 / 共20页
干货表达式树解析框架3Word格式.docx_第2页
第2页 / 共20页
干货表达式树解析框架3Word格式.docx_第3页
第3页 / 共20页
干货表达式树解析框架3Word格式.docx_第4页
第4页 / 共20页
干货表达式树解析框架3Word格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

干货表达式树解析框架3Word格式.docx

《干货表达式树解析框架3Word格式.docx》由会员分享,可在线阅读,更多相关《干货表达式树解析框架3Word格式.docx(20页珍藏版)》请在冰豆网上搜索。

干货表达式树解析框架3Word格式.docx

NULL"

就算是NULL了

  但是这里有个问题,就是原来的操作是先加入符号,再加入Right的,所以这里也要改,改为先放入Right再插入符号

代码如下

classBinaryExpressionParser:

ExpressionParser<

BinaryExpression>

{

publicoverridevoidWhere(BinaryExpressionexpr,ParserArgsargs)

if(ExistsBracket(expr.Left))

args.Builder.Append('

'

);

('

Parser.Where(expr.Left,args);

)'

}

else

varindex=args.Builder.Length;

if(ExistsBracket(expr.Right))

Parser.Where(expr.Right,args);

varlength=args.Builder.Length;

if(length-index==5&

&

args.Builder[length-5]=='

&

args.Builder[length-4]=='

N'

args.Builder[length-3]=='

U'

args.Builder[length-2]=='

L'

args.Builder[length-1]=='

Sign(expr.NodeType,index,args,true);

Sign(expr.NodeType,index,args);

///<

summary>

判断是否需要添加括号

/summary>

privatestaticboolExistsBracket(Expressionexpr)

vars=expr.ToString();

returns!

=null&

s.Length>

5&

s[0]=='

s[1]=='

;

privatestaticvoidSign(ExpressionTypetype,intindex,ParserArgsargs,booluseis=false)

switch(type)

caseExpressionType.And:

caseExpressionType.AndAlso:

args.Builder.Insert(index,"

AND"

break;

caseExpressionType.Equal:

if(useis)

IS"

="

caseExpressionType.GreaterThan:

>

"

caseExpressionType.GreaterThanOrEqual:

="

caseExpressionType.NotEqual:

ISNOT"

<

caseExpressionType.Or:

caseExpressionType.OrElse:

OR"

caseExpressionType.LessThan:

caseExpressionType.LessThanOrEqual:

default:

thrownewNotImplementedException("

无法解释节点类型"

+type);

......

结果

//打印SELECT*FROM[User]uWHEREu.[Name]ISNOTNULL

问题二

u.Name.StartsWith("

bl"

));

//u.Namelike'

bl%'

  这2个表达式只要运行一下就可以知道,他们是无法被解析的,原因就是:

  

  尚未实现MethodCallExpression的解析

  因为2个都属性MethodCall表达式

  所以只需要实现MethodCallExpressionParser即可

  MethodCallExpression方法调用表达式

  Method表示调用的方法  

  Arguments表示方法中用到的参数

  Object表示调用方法的实例对象

  每种方法对应的解析都是不同的,所以我为每个方法都实现一个单独的解析函数

  比如String类中的3个操作,分别对应3种Like的情况

publicstaticvoidString_StartsWith(MethodCallExpressionexpr,ParserArgsargs)

{

publicstaticvoidString_Contains(MethodCallExpressionexpr,ParserArgsargs)

publicstaticvoidString_EndsWith(MethodCallExpressionexpr,ParserArgsargs)

 

  然后将他们加入到一个键值对中(因为方法是有重载的,所以会有一样名字的方法,但是解析方式是相同的)

staticDictionary<

MethodInfo,Action<

MethodCallExpression,ParserArgs>

_Methods=MethodDitcInit();

privatestaticDictionary<

MethodDitcInit()

Dictionary<

dict=newDictionary<

();

vartype=typeof(string);

foreach(varmetintype.GetMethods())

switch(met.Name)

case"

StartsWith"

:

dict.Add(met,String_StartsWith);

Contains"

dict.Add(met,String_Contains);

EndsWith"

dict.Add(met,String_EndsWith);

returndict;

 调用where

publicoverridevoidWhere(MethodCallExpressionexpr,ParserArgsargs)

Action<

act;

if(_Methods.TryGetValue(expr.Method,outact))

act(expr,args);

return;

无法解释方法"

+expr.Method);

  现在分别完成3个String_的函数就可以了

publicstaticvoidString_StartsWith(MethodCallExpressionexpr,ParserArgsargs)

Parser.Where(expr.Object,args);

args.Builder.Append("

LIKE"

Parser.Where(expr.Arguments[0],args);

+'

%'

LIKE'

+"

u.Name.Contains("

u.Name.EndsWith("

/*打印

SELECT*FROM[User]uWHEREu.[Name]LIKE'

bl'

*/

问题三

int[]arr={13,15,17,19,21};

arr.Contains(u.Age));

//u.Agein(13,15,17,19,21)

  这个问题和刚才那个问题有很多相似之处,所以首先需要在MethodCallExpressionParser类中实现一个对应Enumerable.Contains的解析函数

  但是这个方法有一个比较特殊的地方就是他是泛型方法,所以在从键值对中获取处理函数的时候,需要把他转为`泛型方法定义`(MethodInfo.GetGenericMethodDefinition)的才可以

varkey=expr.Method;

if(key.IsGenericMethod)

key=key.GetGenericMethodDefinition();

}

if(_Methods.TryGetValue(key,outact))

  对应的处理函数

publicstaticvoidEnumerable_Contains(MethodCallExpressionexpr,ParserArgsargs)

Parser.Where(expr.Arguments[1],args);

IN"

  看上去似乎已经完成了,但是结果是....

//打印

//SELECT*FROM[User]uWHEREu.[Age]IN'

Demo.Program+<

c__DisplayClass0'

[arr]

问题

  问题在于arr和u.Age一样都是MemberExpression,而MemberExpression的解析之前是这样写的

classMemberExpressionParser:

ExpressionParser<

MemberExpression>

publicoverridevoidWhere(MemberExpressionexpr,ParserArgsargs)

Parser.Where(expr.Expression,args);

['

args.Builder.Append(expr.Member.Name);

]'

  显然MemberExpression有两种,一种是`虚拟的`,是不存在值的,比如u.Age,

  还有一种是真实的比如上面例子中的arr,他是有真实值的

  所以这个地方要改一改

代码

  这块地方比较难,需要理解一下

classMemberExpressionParser:

if(expr.ExpressionisParameterExpression)

objectval=GetValue(expr);

IEnumeratorarray=valasIEnumerator;

if(array!

=null)

AppendArray(args,array);

elseif(valisIEnumerable)

AppendArray(args,((IEnumerable)val).GetEnumerator());

AppendObject(args,val);

获取成员表达式中的实际值

privatestaticobjectGetValue(MemberExpressionexpr)

objectval;

varfield=expr.MemberasFieldInfo;

if(field!

val=field.GetValue(((ConstantExpression)expr.Expression).Value);

val=((PropertyInfo)expr.Member).GetValue(((ConstantExpression)expr.Expression).Value,null);

returnval;

追加可遍历对象(数组或集合或简单迭代器)

privatestaticvoidAppendArray(ParserArgsargs,IEnumeratorarray)

if(array.MoveNext())

AppendObject(args,array.Current);

while(array.MoveNext())

'

NULL"

追加一般对象

publicstaticvoidAppendObject(ParserArgsargs,objectval)

if(val==null||val==DBNull.Value)

elseif(valisbool)

args.Builder.Append(val.GetHashCode());

varcode=(int)Type.GetTypeCode(val.GetType());

if(code>

=5&

code<

=15)//如果expr.Value是数字类型

args.Builder.Append(val);

\'

'

//SELECT*FROM[User]uWHEREu.[Age]IN(13,15,17,19,21)

问题四

如果需要使用参数化传递参数,又需要怎样修改源码呢?

  其实这个问题是最简单的一个问题,如果已经理解这个`框架`的工作原理可以轻松解决这个问题

  1.修改ParserArgs,使其中包含一个SqlParamete的集合,并且为了方便操作,将AppendObject的方法也移入ParserArgs,变为AddParameter

  使用参数化传递还有一个好处可以不用判断参数类型,来确定是否添加单引号('

publicclassParserArgs

publicParserArgs()

Builder=newStringBuilder();

SqlParameters=newList<

SqlParameter>

publicList<

SqlParameters{get;

set;

publicStringBuilderBuilder{get;

privateset;

追加参数

publicvoidAddParameter(objectobj)

if

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1