risc-v中文社区

 找回密码
 立即注册
查看: 736|回复: 0

[经验] C# 表达式目录树Expression的实现

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2022-7-22 17:04:56 | 显示全部楼层 |阅读模式
目录

表达式目录树

表达式目录树:语法树,或者说是一种数据结构
1.表达式目录树expression:system.linq.expressions;
2.描述了多个变量或者和常量之间的关系,按照一定的规则进行组装!

  • 可以向委托一样使用lambd表达式快捷声明;
  • 不能有语句体,声明只能有一行代码;
  • 可以通过compile(),编译成一个委托;
[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em][size=1em]func<int, int, int> func = (m, n) =>
[size=1em]{
[size=1em]    int i = 0;
[size=1em]    return m * n + 2;
[size=1em]};  //委托  拉姆达表达式其实是作为委托的一个参数,本质是一个方法(匿名方法)
[size=1em]expression<func<int, int, int>> exp = (m, n) => m * n + 2; //数据结构--就像对一个计算做了一个精确的描述,展开之后发现,分为左边,右边,每个元素都可以把值都获取出来,二叉树
[size=1em]var erpplu= exp.compile();//表达式目录树可以通过compile 转换成一个委托

[size=1em]//表达式目录树:语法树,或者说是一种数据结构
[size=1em]int iresult1 = func.invoke(12, 23);
[size=1em]int iresult2 = exp.compile().invoke(12, 23);





表达式目录树的拼装

手动拼装表达式目录树,不是用的lambda的快捷方式

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em][size=1em]//表达式目录树的拼装
[size=1em]expression<func<int>> expression = () => 123 + 234;  //两个常量相加-----表达式目录树的快捷声明

[size=1em]expression constant123 = expression.constant(123);
[size=1em]expression constant234 = expression.constant(234);
[size=1em]expression expressionadd = expression.add(constant123, constant234);
[size=1em]var exp = expression.lambda<func<int>>(expressionadd);
[size=1em]var func = exp.compile();
[size=1em]int iresult = func.invoke();




[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em][size=1em]expression<func<int, int, int>> exp = (m, n) => m * n + m + n + 2; //快捷声明--其实编译器提供的便捷功能---语法糖--具体实现可通过反编译工具查看

[size=1em]//具体实现可通过反编译工具查看
[size=1em]parameterexpression parameterexpression = expression.parameter(typeof(int), "m");
[size=1em]parameterexpression parameterexpression2 = expression.parameter(typeof(int), "n");
[size=1em]expression expcontant2 = expression.constant(2, typeof(int));

[size=1em]expression multipley = expression.multiply(parameterexpression, parameterexpression2);
[size=1em]expression expadd = expression.add(multipley, parameterexpression);

[size=1em]expression expadd1 = expression.add(expadd, parameterexpression2);
[size=1em]expression expadd2 = expression.add(expadd1, expcontant2);
[size=1em]expression<func<int, int, int>> expression = expression.lambda<func<int, int, int>>(expadd2, new parameterexpression[]
[size=1em]{
[size=1em]parameterexpression,
[size=1em]parameterexpression2
[size=1em]});
[size=1em]func<int, int, int> fun = expression.compile();
[size=1em]int iresult = fun.invoke(10, 11);




[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em][size=1em]var peoplequery = new list<people>().asqueryable();
[size=1em]expression<func<people, bool>> lambda = x => x.id.tostring().equals("5");
[size=1em]peoplequery.where(lambda);

[size=1em]parameterexpression parameterexpression = expression.parameter(typeof(people), "x");
[size=1em]fieldinfo idfield = typeof(people).getfield("id");
[size=1em]var idexp = expression.field(parameterexpression, idfield);

[size=1em]methodinfo tostring = typeof(int).getmethod("tostring", new type[0]);
[size=1em]var tostringexp = expression.call(idexp, tostring, array.empty<expression>());
[size=1em]var equals = typeof(string).getmethod("equals", new type[] { typeof(string) });
[size=1em]expression expressionconstant5 = expression.constant("5", typeof(string));
[size=1em]var equalsexp = expression.call(tostringexp, equals, new expression[]
[size=1em] {
[size=1em]    expressionconstant5
[size=1em] });
[size=1em]expression<func<people, bool>> expression = expression.lambda<func<people, bool>>(equalsexp, new parameterexpression[]
[size=1em]{
[size=1em] parameterexpression
[size=1em]});
[size=1em]func<people, bool> func = expression.compile();
[size=1em]var bresult = func.invoke(new people()
[size=1em]{
[size=1em]    id = 5,
[size=1em]    name = "海贝"
[size=1em]});

[size=1em]new list<people>().asqueryable().where(expression);





应用
linq to sql[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em][size=1em]var dbset = new list<people>().asqueryable();//ef dbset
[size=1em]dbset.where(p => p.age == 25 & p.name.contains("阳光下的微笑"));

[size=1em]expression<func<people, bool>> exp = null;
[size=1em]console.writeline("用户输入个名称,为空就跳过");
[size=1em]string name = console.readline();
[size=1em]if (!string.isnullorwhitespace(name))
[size=1em]{
[size=1em]    exp = p => p.name.contains(name);
[size=1em]}
[size=1em]console.writeline("用户输入个最小年纪,为空就跳过");
[size=1em]string age = console.readline();
[size=1em]if (!string.isnullorwhitespace(age) && int.tryparse(age, out int iage))
[size=1em]{
[size=1em]    exp = p => p.age > iage;
[size=1em]}




上面的玩法是不是只有最后一个条件才生效?如果需要多个条件都满足;怎么办? 当然是拼装啊;
拼装可以从最小粒度来组装表达式目录树;如果有一个封装,你把各种条件给我,我从最小粒度开始一个一个的拼装起来,不就是一个长的表达式目录树了吗?

解决方案:
调用方可以组装一个很长的表达式目录树传递过来;
表达式目录树传递过来以后,在这里应该做什么?应该解析;
所有信息都在表达式目录树里面,自然也可以把他解析(找出来)
解析就可以通过expressionvisitor解析----生成对应的sql语句;


expressionvisitor

表达式目录树的访问者----访问者模式;
1.visit方法–访问表达式目录树的入口—分辨是什么类型的表达式目录
2.调度到更加专业的方法中进一步访问,访问一遍之后,生成一个新的表达式目录 —有点像递归,不全是递归;
3.因为表达式目录树是个二叉树,expressionvisitor一直往下访问,一直到叶节点;那就访问了所有的节点;
4.在访问的任何一个环节,都可以拿到对应当前环节的内容(参数名称、参数值。。),就可以进一步扩展;

为什么要使用表达式目录树来拼装解析呢:
1.可以提高重用性;
2.如果封装好一个方法,接受一个表达式目录树,在解析的时候,其实就是不断的访问,访问有规则;
3.任何一个表达式目录树都可以调用当前方法来解析;
4.表达式目录树可以支持泛型;

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em][size=1em]{
[size=1em]    expression<func<people, bool>> lambda = x => x.age > 5 && x.id > 5
[size=1em]                                             && x.name.startswith("1") //  like '1%'
[size=1em]                                             && x.name.endswith("1") //  like '%1'
[size=1em]                                             && x.name.contains("1");//  like '%1%'

[size=1em]    //string sql = string.format("delete from [{0}] where [age]>5 and [id] >5"
[size=1em]        , typeof(people).name
[size=1em]        , " [age]>5 and [id] >5" );

[size=1em]    conditionbuildervisitor vistor = new conditionbuildervisitor();
[size=1em]    vistor.visit(lambda);
[size=1em]    console.writeline(vistor.condition());
[size=1em]}
[size=1em]{
[size=1em]   // ((( [age] > '5') and( [name] =  [name] )) or( [id] > '5' ))
[size=1em]   string name = "aaa";
[size=1em]    expression<func<people, bool>> lambda = x => x.age > 5 && x.name == name || x.id > 5;
[size=1em]    conditionbuildervisitor vistor = new conditionbuildervisitor();
[size=1em]    vistor.visit(lambda);
[size=1em]    console.writeline(vistor.condition());
[size=1em]}
[size=1em]{
[size=1em]    expression<func<people, bool>> lambda = x => x.age > 5 || (x.name == "a" && x.id > 5);
[size=1em]    conditionbuildervisitor vistor = new conditionbuildervisitor();
[size=1em]    vistor.visit(lambda);
[size=1em]    console.writeline(vistor.condition());
[size=1em]}
[size=1em]{
[size=1em]    expression<func<people, bool>> lambda = x => (x.age > 5 || x.name == "a") && x.id > 5;
[size=1em]    conditionbuildervisitor vistor = new conditionbuildervisitor();
[size=1em]    vistor.visit(lambda);
[size=1em]    console.writeline(vistor.condition());
[size=1em]}




自己封装的解析器,这就是ef6的底层原理,根据表达式树自动生成相应的sql语句。

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em]48

[size=1em]49

[size=1em]50

[size=1em]51

[size=1em]52

[size=1em]53

[size=1em]54

[size=1em]55

[size=1em]56

[size=1em]57

[size=1em]58

[size=1em]59

[size=1em]60

[size=1em]61

[size=1em]62

[size=1em]63

[size=1em]64

[size=1em]65

[size=1em]66

[size=1em]67

[size=1em]68

[size=1em]69

[size=1em]70

[size=1em]71

[size=1em]72

[size=1em]73

[size=1em]74

[size=1em]75

[size=1em]76

[size=1em]77

[size=1em]78

[size=1em]79

[size=1em]80

[size=1em]81

[size=1em]82

[size=1em]83

[size=1em]84

[size=1em]85

[size=1em]86

[size=1em]87

[size=1em]88

[size=1em]89

[size=1em]90

[size=1em]91

[size=1em]92

[size=1em]93

[size=1em]94

[size=1em]95

[size=1em]96

[size=1em]97

[size=1em]98

[size=1em]99

[size=1em]100

[size=1em]101

[size=1em]102

[size=1em]103

[size=1em]104

[size=1em]105

[size=1em]106

[size=1em]107

[size=1em]108

[size=1em]109

[size=1em]110

[size=1em]111

[size=1em]112

[size=1em]113

[size=1em][size=1em]public class conditionbuildervisitor : expressionvisitor
[size=1em]{
[size=1em]    private stack<string> _stringstack = new stack<string>();

[size=1em]    public string condition()
[size=1em]    {
[size=1em]        string condition = string.concat(this._stringstack.toarray());
[size=1em]        this._stringstack.clear();
[size=1em]        return condition;
[size=1em]    }

[size=1em]    /// <summary>
[size=1em]    /// 如果是二元表达式
[size=1em]    /// </summary>
[size=1em]    /// <param name="node"></param>
[size=1em]    /// <returns></returns>
[size=1em]    protected override expression visitbinary(binaryexpression node)
[size=1em]    {
[size=1em]        if (node == null) throw new argumentnullexception("binaryexpression");

[size=1em]        this._stringstack.push(")");
[size=1em]        base.visit(node.right);//解析右边
[size=1em]        this._stringstack.push(" " + node.nodetype.tosqloperator() + " ");
[size=1em]        base.visit(node.left);//解析左边
[size=1em]        this._stringstack.push("(");

[size=1em]        return node;
[size=1em]    }

[size=1em]    /// <summary>
[size=1em]    /// 解析属性
[size=1em]    /// </summary>
[size=1em]    /// <param name="node"></param>
[size=1em]    /// <returns></returns>
[size=1em]    protected override expression visitmember(memberexpression node)
[size=1em]    {
[size=1em]        if (node == null) throw new argumentnullexception("memberexpression");
[size=1em]        //this._stringstack.push(" [" + node.member.name + "] ");
[size=1em]        return node;
[size=1em]        if (node.expression is constantexpression)
[size=1em]        {
[size=1em]            var value1 = this.invokevalue(node);
[size=1em]            var value2 = this.reflectionvalue(node);
[size=1em]            //this.conditionstack.push($"'{value1}'");
[size=1em]            this._stringstack.push("'" + value2 + "'");
[size=1em]        }
[size=1em]        else
[size=1em]        {
[size=1em]            this._stringstack.push(" [" + node.member.name + "] ");
[size=1em]        }
[size=1em]        return node;
[size=1em]    }


[size=1em]    private object invokevalue(memberexpression member)
[size=1em]    {
[size=1em]        var objexp = expression.convert(member, typeof(object));//struct需要
[size=1em]        return expression.lambda<func<object>>(objexp).compile().invoke();
[size=1em]    }

[size=1em]    private object reflectionvalue(memberexpression member)
[size=1em]    {
[size=1em]        var obj = (member.expression as constantexpression).value;
[size=1em]        return (member.member as fieldinfo).getvalue(obj);
[size=1em]    }

[size=1em]    /// <summary>
[size=1em]    /// 常量表达式
[size=1em]    /// </summary>
[size=1em]    /// <param name="node"></param>
[size=1em]    /// <returns></returns>
[size=1em]    protected override expression visitconstant(constantexpression node)
[size=1em]    {
[size=1em]        if (node == null) throw new argumentnullexception("constantexpression");
[size=1em]        this._stringstack.push(" '" + node.value + "' ");
[size=1em]        return node;
[size=1em]    }
[size=1em]    /// <summary>
[size=1em]    /// 方法表达式
[size=1em]    /// </summary>
[size=1em]    /// <param name="m"></param>
[size=1em]    /// <returns></returns>
[size=1em]    protected override expression visitmethodcall(methodcallexpression m)
[size=1em]    {
[size=1em]        if (m == null) throw new argumentnullexception("methodcallexpression");

[size=1em]        string format;
[size=1em]        switch (m.method.name)
[size=1em]        {
[size=1em]            case "startswith":
[size=1em]                format = "({0} like {1}+'%')";
[size=1em]                break;

[size=1em]            case "contains":
[size=1em]                format = "({0} like '%'+{1}+'%')";
[size=1em]                break;

[size=1em]            case "endswith":
[size=1em]                format = "({0} like '%'+{1})";
[size=1em]                break;

[size=1em]            default:
[size=1em]                throw new notsupportedexception(m.nodetype + " is not supported!");
[size=1em]        }
[size=1em]        this.visit(m.object);
[size=1em]        this.visit(m.arguments[0]);
[size=1em]        string right = this._stringstack.pop();
[size=1em]        string left = this._stringstack.pop();
[size=1em]        this._stringstack.push(string.format(format, left, right));

[size=1em]        return m;
[size=1em]    }
[size=1em]}




[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em][size=1em]internal static class sqloperator
[size=1em]{
[size=1em]    internal static string tosqloperator(this expressiontype type)
[size=1em]    {
[size=1em]        switch (type)
[size=1em]        {
[size=1em]            case (expressiontype.andalso):
[size=1em]            case (expressiontype.and):
[size=1em]                return "and";
[size=1em]            case (expressiontype.orelse):
[size=1em]            case (expressiontype.or):
[size=1em]                return "or";
[size=1em]            case (expressiontype.not):
[size=1em]                return "not";
[size=1em]            case (expressiontype.notequal):
[size=1em]                return "<>";
[size=1em]            case expressiontype.greaterthan:
[size=1em]                return ">";
[size=1em]            case expressiontype.greaterthanorequal:
[size=1em]                return ">=";
[size=1em]            case expressiontype.lessthan:
[size=1em]                return "<";
[size=1em]            case expressiontype.lessthanorequal:
[size=1em]                return "<=";
[size=1em]            case (expressiontype.equal):
[size=1em]                return "=";
[size=1em]            default:
[size=1em]                throw new exception("不支持该方法");
[size=1em]        }

[size=1em]    }
[size=1em]}





表达式目录扩展

表达式目录树动态拼接的实现方式:

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em]48

[size=1em]49

[size=1em]50

[size=1em][size=1em]/// <summary>
[size=1em]/// 合并表达式 and or  not扩展
[size=1em]/// </summary>
[size=1em]public static class expressionextend
[size=1em]{
[size=1em]    /// <summary>
[size=1em]    /// 合并表达式 expr1 and expr2
[size=1em]    /// </summary>
[size=1em]    /// <typeparam name="t"></typeparam>
[size=1em]    /// <param name="expr1"></param>
[size=1em]    /// <param name="expr2"></param>
[size=1em]    /// <returns></returns>
[size=1em]    public static expression<func<t, bool>> and<t>(this expression<func<t, bool>> expr1, expression<func<t, bool>> expr2)
[size=1em]    {
[size=1em]        //return expression.lambda<func<t, bool>>(expression.andalso(expr1.body, expr2.body), expr1.parameters); 错误的写法,两个表达式不是同一个参数
[size=1em]        //将两个表达式的参数统一为参数c
[size=1em]        parameterexpression newparameter = expression.parameter(typeof(t), "c");
[size=1em]        newexpressionvisitor visitor = new newexpressionvisitor(newparameter);
[size=1em]        var left = visitor.replace(expr1.body);
[size=1em]        var right = visitor.replace(expr2.body); //为了能够生成一个新的表达式目录树
[size=1em]        var body = expression.and(left, right);
[size=1em]         return expression.lambda<func<t, bool>>(body, newparameter);

[size=1em]    }
[size=1em]    /// <summary>
[size=1em]    /// 合并表达式 expr1 or expr2
[size=1em]    /// </summary>
[size=1em]    /// <typeparam name="t"></typeparam>
[size=1em]    /// <param name="expr1"></param>
[size=1em]    /// <param name="expr2"></param>
[size=1em]    /// <returns></returns>
[size=1em]    public static expression<func<t, bool>> or<t>(this expression<func<t, bool>> expr1, expression<func<t, bool>> expr2)
[size=1em]    {

[size=1em]        parameterexpression newparameter = expression.parameter(typeof(t), "c");
[size=1em]        newexpressionvisitor visitor = new newexpressionvisitor(newparameter);

[size=1em]        var left = visitor.replace(expr1.body);
[size=1em]        var right = visitor.replace(expr2.body);
[size=1em]        var body = expression.or(left, right);
[size=1em]        return expression.lambda<func<t, bool>>(body, newparameter);
[size=1em]    }
[size=1em]    public static expression<func<t, bool>> not<t>(this expression<func<t, bool>> expr)
[size=1em]    {
[size=1em]        var candidateexpr = expr.parameters[0];
[size=1em]        var body = expression.not(expr.body);

[size=1em]        return expression.lambda<func<t, bool>>(body, candidateexpr);
[size=1em]    }
[size=1em]}




[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em][size=1em]/// <summary>
[size=1em]/// 建立新表达式
[size=1em]/// </summary>
[size=1em]internal class newexpressionvisitor : expressionvisitor
[size=1em]{
[size=1em]    public parameterexpression _newparameter { get; private set; }
[size=1em]    public newexpressionvisitor(parameterexpression param)
[size=1em]    {
[size=1em]        this._newparameter = param;
[size=1em]    }
[size=1em]    public expression replace(expression exp)
[size=1em]    {
[size=1em]        return this.visit(exp);
[size=1em]    }
[size=1em]    protected override expression visitparameter(parameterexpression node)
[size=1em]    {
[size=1em]        return this._newparameter;
[size=1em]    }
[size=1em]}




调用方如下:

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em][size=1em]    {
[size=1em]        expression<func<people, bool>> lambda1 = x => x.age > 5;  
[size=1em]        expression<func<people, bool>> lambda2 = x => x.id > 5;

[size=1em]        //expression<func<people, bool>> newexpress = x => x.age > 5 && x.id > 5;

[size=1em]        expression<func<people, bool>> lambda3 = lambda1.and(lambda2); //且
[size=1em]        expression<func<people, bool>> lambda4 = lambda1.or(lambda2);//或
[size=1em]        expression<func<people, bool>> lambda5 = lambda1.not();//非
[size=1em]        do1(lambda3);
[size=1em]        do1(lambda4);
[size=1em]        do1(lambda5);
[size=1em]    }

[size=1em]private static void do1(expression<func<people, bool>> func)
[size=1em]{
[size=1em]    list<people> people = new list<people>()
[size=1em]    {
[size=1em]        new people(){id=4,name="123",age=4},
[size=1em]        new people(){id=5,name="234",age=5},
[size=1em]        new people(){id=6,name="345",age=6},
[size=1em]    };

[size=1em]    list<people> peoplelist = people.where(func.compile()).tolist();
[size=1em]}




对象深拷贝

硬编码

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em][size=1em]peoplecopy peoplecopy = new peoplecopy()
[size=1em]{
[size=1em]    id = people.id,
[size=1em]    name = people.name,
[size=1em]    age = people.age
[size=1em]};




通过反射实现

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em][size=1em]public class reflectionmapper
[size=1em]{
[size=1em]    /// <summary>
[size=1em]    /// 反射
[size=1em]    /// </summary>
[size=1em]    /// <typeparam name="tin"></typeparam>
[size=1em]    /// <typeparam name="tout"></typeparam>
[size=1em]    /// <param name="tin"></param>
[size=1em]    /// <returns></returns>
[size=1em]    public static tout trans<tin, tout>(tin tin)
[size=1em]    {
[size=1em]        tout tout = activator.createinstance<tout>();
[size=1em]        foreach (var itemout in tout.gettype().getproperties())
[size=1em]        {
[size=1em]            var propin = tin.gettype().getproperty(itemout.name);
[size=1em]            itemout.setvalue(tout, propin.getvalue(tin));
[size=1em]        }

[size=1em]        foreach (var itemout in tout.gettype().getfields())
[size=1em]        {
[size=1em]            var fieldin = tin.gettype().getfield(itemout.name);
[size=1em]            itemout.setvalue(tout, fieldin.getvalue(tin));
[size=1em]        }
[size=1em]        return tout;
[size=1em]    }
[size=1em]}




通过序列化实现

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em][size=1em]/// <summary>
[size=1em]/// 使用第三方序列化反序列化工具
[size=1em]/// 还有automapper
[size=1em]/// </summary>
[size=1em]public class serializemapper
[size=1em]{
[size=1em]    /// <summary>
[size=1em]    /// 序列化反序列化方式
[size=1em]    /// </summary>
[size=1em]    /// <typeparam name="tin"></typeparam>
[size=1em]    /// <typeparam name="tout"></typeparam>
[size=1em]    public static tout trans<tin, tout>(tin tin)
[size=1em]    {
[size=1em]        return jsonconvert.deserializeobject<tout>(jsonconvert.serializeobject(tin));
[size=1em]    }
[size=1em]}




反射和序列化两种实现方式性能不太好;


通过表达式目录树实现

通过表达式目录树动态的生成硬编码

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em][size=1em]func<people, peoplecopy> func = p => new peoplecopy()
[size=1em]{
[size=1em]    id = p.id,
[size=1em]    name = p.name,
[size=1em]    age = p.age
[size=1em]};
[size=1em]peoplecopy peoplecopy3 = func.invoke(people);




方法一:普通缓存

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em][size=1em]/// <summary>
[size=1em]/// 生成表达式目录树 缓存
[size=1em]/// </summary>
[size=1em]public class expressionmapper
[size=1em]{
[size=1em]    /// <summary>
[size=1em]    /// 字典缓存--hash分布
[size=1em]    /// </summary>
[size=1em]    private static dictionary<string, object> _dic = new dictionary<string, object>();

[size=1em]    /// <summary>
[size=1em]    /// 字典缓存表达式树
[size=1em]    /// </summary>
[size=1em]    /// <typeparam name="tin"></typeparam>
[size=1em]    /// <typeparam name="tout"></typeparam>
[size=1em]    /// <param name="tin"></param>
[size=1em]    /// <returns></returns>
[size=1em]    public static tout trans<tin, tout>(tin tin)
[size=1em]    {
[size=1em]        string key = string.format("funckey_{0}_{1}", typeof(tin).fullname, typeof(tout).fullname);
[size=1em]        if (!_dic.containskey(key))
[size=1em]        {
[size=1em]            parameterexpression parameterexpression = expression.parameter(typeof(tin), "p");
[size=1em]            list<memberbinding> memberbindinglist = new list<memberbinding>();
[size=1em]            foreach (var item in typeof(tout).getproperties())
[size=1em]            {
[size=1em]                memberexpression property = expression.property(parameterexpression, typeof(tin).getproperty(item.name));
[size=1em]                memberbinding memberbinding = expression.bind(item, property);
[size=1em]                memberbindinglist.add(memberbinding);
[size=1em]            }
[size=1em]            foreach (var item in typeof(tout).getfields())
[size=1em]            {
[size=1em]                memberexpression property = expression.field(parameterexpression, typeof(tin).getfield(item.name));
[size=1em]                memberbinding memberbinding = expression.bind(item, property);
[size=1em]                memberbindinglist.add(memberbinding);
[size=1em]            }
[size=1em]            memberinitexpression memberinitexpression = expression.memberinit(expression.new(typeof(tout)), memberbindinglist.toarray());
[size=1em]            expression<func<tin, tout>> lambda = expression.lambda<func<tin, tout>>(memberinitexpression, new parameterexpression[]
[size=1em]            {
[size=1em]                parameterexpression
[size=1em]            });
[size=1em]            func<tin, tout> func = lambda.compile();//拼装是一次性的
[size=1em]            _dic[key] = func;
[size=1em]        }
[size=1em]        return ((func<tin, tout>)_dic[key]).invoke(tin);
[size=1em]    }
[size=1em]}




方法二:泛型缓存,性能较高

[size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em][size=1em]/// <summary>
[size=1em]/// 生成表达式目录树  泛型缓存
[size=1em]/// </summary>
[size=1em]/// <typeparam name="tin"></typeparam>
[size=1em]/// <typeparam name="tout"></typeparam>
[size=1em]public class expressiongenericmapper<tin, tout>//mapper`2
[size=1em]{
[size=1em]    private static func<tin, tout> _func = null;
[size=1em]    static expressiongenericmapper()
[size=1em]    {
[size=1em]        parameterexpression parameterexpression = expression.parameter(typeof(tin), "p");
[size=1em]        list<memberbinding> memberbindinglist = new list<memberbinding>();
[size=1em]        foreach (var item in typeof(tout).getproperties())
[size=1em]        {
[size=1em]            memberexpression property = expression.property(parameterexpression, typeof(tin).getproperty(item.name));
[size=1em]            memberbinding memberbinding = expression.bind(item, property);
[size=1em]            memberbindinglist.add(memberbinding);
[size=1em]        }
[size=1em]        foreach (var item in typeof(tout).getfields())
[size=1em]        {
[size=1em]            memberexpression property = expression.field(parameterexpression, typeof(tin).getfield(item.name));
[size=1em]            memberbinding memberbinding = expression.bind(item, property);
[size=1em]            memberbindinglist.add(memberbinding);
[size=1em]        }
[size=1em]        memberinitexpression memberinitexpression = expression.memberinit(expression.new(typeof(tout)), memberbindinglist.toarray());
[size=1em]        expression<func<tin, tout>> lambda = expression.lambda<func<tin, tout>>(memberinitexpression, new parameterexpression[]
[size=1em]        {
[size=1em]                parameterexpression
[size=1em]        });
[size=1em]        _func = lambda.compile();//拼装是一次性的
[size=1em]    }
[size=1em]    public static tout trans(tin t)
[size=1em]    {
[size=1em]        return _func(t);
[size=1em]    }
[size=1em]}

本贴来源:帖子




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-4-19 18:11 , Processed in 0.031363 second(s), 17 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表