孙俪 发表于 2023-5-18 21:49:42

链式-父类中返回子类对象

一晃五年没写博客了,依旧再C#上耕耘,依旧没有啥建树,现在也不知道.net上还有多少人再使用,在这里分享一些自己觉得写的还算优雅的代码。
对于自己写着完的代码,我特别喜欢链式(来源于jQuery的影响吧),大部分时候链式就是将返回值为void类型的对象,返回this指针,直到我遇到一个特殊情况——在父类中返回子类类型。大部分情况父类都不知道子类有什么,根本没有返回子类的需求
但是由于链式调用父类的接口返回父类对象,就无法继续链式了。说明可能不清楚,直接show code
1public class OldWhereV2<T>
2   {
3         protected Expression<Func<T, bool>> expression = null;
4
5         public OldWhereV2<T> Where(Expression<Func<T, bool>> memberExpression)
6         {
7             return this;
8         }
9
10         public OldWhereV2<T> Or(Expression<Func<T, bool>> memberExpression)
11         {
12             return this;
13         }
14
15         public OldWhereV2<T> Add(Expression<Func<T, bool>> memberExpression)
16         {
17             return this;
18         }
19   }
20
21   public class OldQeuryV2<T> : OldWhereV2<T>
22   {
23
24         public OldQeuryV2<T> Select(Expression<Func<T, object>> memberExpression)
25         {
26             return this;
27         }
28
29         public OldQeuryV2<T> Take(int count)
30         {
31             return this;
32         }
33
34         public OldQeuryV2<T> Order(Expression<Func<T, object>> memberExpression, bool asc)
35         {
36             return this;
37         }
38   }调用的时候,如果使用链式
1var query =new OldQeuryV2<Train>()
2                .Select(x => x.Apply_Time)
3                .Select(x => x.Apply_Time)
4                .Select(x => x.Approval_OrgName)
5                .Where(x => x.Create_Time > DateTime.Now)
6                .Add(x => x.Approval_OrgName == "")
7                .Order(x => x.Approval_OrgGID, true)
8                .Order(x => x.Apply_Time, false)
9                .Take(10); .Order(x => x.Approval_OrgGID, true) 这行代码会报错的。因为Where返回的是OldWhereV2类型,而Order方法要求OldQeuryV2类型
 这个问题困扰我一晚,后来我记得在哪里看过一本书,书中有泛型自包含的例子,但是当时完全看不懂,但是此处感觉使用完全没毛病所以就做了简单修改
1public abstract class Condition<T, M> where M : Condition<T, M>
2   {
3         protected Expression<Func<T, bool>> expression = null;
4
5         public M Where(Expression<Func<T, bool>> memberExpression)
6         {
7             expression = memberExpression;
8             return (M)this;
9         }
10
11         public M Or(Expression<Func<T, bool>> memberExpression)
12         {
13             if (expression == null)
14             {
15               expression = memberExpression;
16             }
17             else
18             {
19               var invokedExpr = Expression.Invoke(memberExpression, expression.Parameters.Cast<Expression>());
20               expression = Expression.Lambda<Func<T, bool>>(Expression.OrElse(expression.Body, invokedExpr), expression.Parameters);
21             }
22             return (M)this;
23         }
24
25         public M Add(Expression<Func<T, bool>> memberExpression)
26         {
27             if (expression == null)
28             {
29               expression = memberExpression;
30             }
31             else
32             {
33               var invokedExpr = Expression.Invoke(memberExpression, expression.Parameters.Cast<Expression>());
34               expression = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expression.Body, invokedExpr), expression.Parameters);
35             }
36             return (M)this;
37         }
38   }
39
40   public class Qeury<T> : Condition<T, Qeury<T>>
41   {
42         List<MemberInfo> selects = new List<MemberInfo>();
43         Dictionary<MemberInfo, bool> orders = new Dictionary<MemberInfo, bool>();
44         int count = 1000;
45
46         public Qeury<T> Select(Expression<Func<T, object>> memberExpression)
47         {
48             MemberInfo memberInfo = memberExpression.GetMemberInfo();
49             if (!selects.Contains(memberInfo))
50             {
51               selects.Add(memberInfo);
52             }
53             return this;
54         }
55
56         public Qeury<T> Take(int count)
57         {
58             this.count = count;
59             return this;
60         }
61
62         public Qeury<T> Order(Expression<Func<T, object>> memberExpression, bool asc)
63         {
64             MemberInfo memberInfo = memberExpression.GetMemberInfo();
65             if (orders.ContainsKey(memberInfo))
66             {
67               orders = asc;
68             }
69             else
70             {
71               orders.Add(memberInfo, asc);
72             }
73             return this;
74         }
75
76         public string QeurySql()
77         {
78             var queryInfo = new QueryInfo()
79             {
80               WhereExpression = this.expression,
81               SelectFields = this.selects,
82               Orders = this.orders,
83               Count = this.count
84             };
85
86             return TableAnalysis.GetTableInfo(typeof(T)).QeurySql(queryInfo);
87         }
88   }这里将Condition类修改为Condition 而M是Condition的子类,返回的时候只需要返回M类型就好了,当然由于Condition返回了子类,所以我把它设置成了抽象类,但是也可以不用。由于Qeury :实现了Condition,所以子类就可以正常调用父类的方法了。
具体例子如下:
1 var query =new Qeury<Train>()
2                .Select(x => x.Apply_Time)
3                .Select(x => x.Apply_Time)
4                .Select(x => x.Approval_OrgName)
5                .Where(x => x.Create_Time > DateTime.Now)
6                .Add(x => x.Approval_OrgName == "")
7                .Order(x => x.Approval_OrgGID, true)
8                .Order(x => x.Apply_Time, false)
9                .Take(10);这个算是奇技淫巧,发出来给大家看看,不过不链式不久没有烦恼了吗,正常如下面定义就好了
1   public class OldCondition<T>
2   {
3         public void Where(Expression<Func<T, bool>> memberExpression)
4         {
5
6         }
7
8         public void Or(Expression<Func<T, bool>> memberExpression)
9         {
10
11         }
12
13         public void Add(Expression<Func<T, bool>> memberExpression)
14         {
15
16         }
17   }
18
19   public class OldQeury<T> : OldCondition<T>
20   {
21         public void Select(Expression<Func<T, object>> memberExpression)
22         {
23
24         }
25
26         public void Take(int count)
27         {
28
29         }
30
31         public void Order(Expression<Func<T, object>> memberExpression, bool asc)
32         {
33
34         }
35   }View Code 

来源:https://www.cnblogs.com/watermoon2/archive/2023/05/18/17412967.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 链式-父类中返回子类对象