链式-父类中返回子类对象
一晃五年没写博客了,依旧再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]