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

打印 上一主题 下一主题

主题 580|帖子 580|积分 1740

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

数据人与超自然意识

金牌会员
这个人很懒什么都没写!

标签云

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