44using System . Linq ;
55using System . Linq . Expressions ;
66using System . Reflection ;
7+ using ShardingCore . Exceptions ;
78using ShardingCore . Extensions ;
89
910namespace ShardingCore . Sharding . Enumerators . AggregateExtensions
@@ -98,11 +99,20 @@ public static object Count(this IQueryable source, string propertyName)
9899
99100 return source . Count ( property ) ;
100101 }
101- public static object Sum ( this IQueryable source , PropertyInfo property )
102+ /// <summary>
103+ /// 根据属性求和
104+ /// </summary>
105+ /// <param name="source"></param>
106+ /// <param name="property"></param>
107+ /// <returns></returns>
108+ /// <exception cref="ArgumentNullException"></exception>
109+ public static object SumByProperty ( this IQueryable source , PropertyInfo property )
102110 {
103111 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
104112 if ( property == null ) throw new ArgumentNullException ( nameof ( property ) ) ;
105-
113+ if ( ! property . PropertyType . IsNumericType ( ) )
114+ throw new ShardingCoreInvalidOperationException (
115+ $ "method sum cant calc type :[{ property . PropertyType } ]") ;
106116 ParameterExpression parameter = Expression . Parameter ( source . ElementType , "s" ) ;
107117 MemberExpression getter = Expression . MakeMemberAccess ( parameter , property ) ;
108118 Expression selector = Expression . Lambda ( getter , parameter ) ;
@@ -120,14 +130,20 @@ public static object Sum(this IQueryable source, PropertyInfo property)
120130
121131 return source . Provider . Execute ( callExpression ) ;
122132 }
123- [ ExcludeFromCodeCoverage ]
124- public static object Sum ( this IQueryable source , string propertyName )
133+ /// <summary>
134+ /// 根据属性求和
135+ /// </summary>
136+ /// <param name="source"></param>
137+ /// <param name="propertyName"></param>
138+ /// <returns></returns>
139+ /// <exception cref="ArgumentNullException"></exception>
140+ public static object SumByPropertyName ( this IQueryable source , string propertyName )
125141 {
126142 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
127143 if ( propertyName == null ) throw new ArgumentNullException ( nameof ( propertyName ) ) ;
128144
129145 PropertyInfo property = source . ElementType . GetProperty ( propertyName ) ;
130- return source . Sum ( property ) ;
146+ return source . SumByProperty ( property ) ;
131147 }
132148 //public static object Average(this IQueryable source, string member)
133149 //{
@@ -160,7 +176,7 @@ public static object Sum(this IQueryable source, string propertyName)
160176 // && m.IsGenericMethod);
161177
162178 // // Now that we have the correct method, we need to know how to call the method.
163- // // Note that the Queryable.Sum <TSource>(source, selector) has a generic type,
179+ // // Note that the Queryable.SumByProperty <TSource>(source, selector) has a generic type,
164180 // // which we haven't resolved yet. Good thing is that we can use copy the one from
165181 // // our initial source expression.
166182 // var genericAvgMethod = avgMethod.MakeGenericMethod(new[] {source.ElementType});
@@ -253,28 +269,46 @@ public static object Min(this IQueryable source, PropertyInfo property)
253269 /// <param name="source">数据源</param>
254270 /// <param name="averagePropertyName">聚合函数average属性名</param>
255271 /// <param name="countPropertyName">聚合函数count属性名</param>
272+ /// <param name="resultType">平均值返回结果:int/int=double</param>
256273 [ ExcludeFromCodeCoverage ]
257- public static object AverageWithCount ( this IQueryable source , string averagePropertyName , string countPropertyName )
274+ public static object AverageWithCount ( this IQueryable source , string averagePropertyName , string countPropertyName , Type resultType )
258275 {
259276 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
260277 if ( averagePropertyName == null ) throw new ArgumentNullException ( nameof ( averagePropertyName ) ) ;
261278 if ( countPropertyName == null ) throw new ArgumentNullException ( nameof ( countPropertyName ) ) ;
262279 var averageProperty = source . ElementType . GetProperty ( averagePropertyName ) ;
263280 var countProperty = source . ElementType . GetProperty ( countPropertyName ) ;
264- return source . AverageWithCount ( averageProperty , countProperty ) ;
281+ return source . AverageWithCount ( averageProperty , countProperty , resultType ) ;
265282 }
266- public static object AverageWithCount ( this IQueryable source , PropertyInfo averageProperty , PropertyInfo countProperty )
283+ public static object AverageWithCount ( this IQueryable source , PropertyInfo averageProperty , PropertyInfo countProperty , Type resultType )
267284 {
268285 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
269286 if ( averageProperty == null ) throw new ArgumentNullException ( nameof ( averageProperty ) ) ;
270287 if ( countProperty == null ) throw new ArgumentNullException ( nameof ( countProperty ) ) ;
271288 //获取sum
272289 var sum = source . AverageSum ( averageProperty , countProperty ) ;
273- var count = source . Sum ( countProperty ) ;
274- var constantSum = Expression . Constant ( sum ) ;
275- var constantCount = Expression . Constant ( count ) ;
276- var unaryExpression = Expression . Convert ( constantCount , sum . GetType ( ) ) ;
277- var binaryExpression = Expression . Divide ( constantSum , unaryExpression ) ;
290+ var count = source . SumByProperty ( countProperty ) ;
291+ return AverageConstant ( sum , count , resultType ) ;
292+ //var constantSum = Expression.Constant(sum);
293+ //var constantCount = Expression.Constant(count);
294+ //var unaryExpression = Expression.Convert(constantCount, sum.GetType());
295+ //var binaryExpression = Expression.Divide(constantSum, unaryExpression);
296+ //var invoke = Expression.Lambda(binaryExpression).Compile().DynamicInvoke();
297+ //return invoke;
298+ }
299+
300+ public static object AverageConstant ( object sum , object count , Type resultType )
301+ {
302+
303+ Expression constantSum = Expression . Constant ( sum ) ;
304+ //如果计算类型和返回类型不一致先转成一致
305+ if ( sum . GetType ( ) != resultType )
306+ constantSum = Expression . Convert ( constantSum , resultType ) ;
307+ Expression constantCount = Expression . Constant ( count ) ;
308+ //如果计算类型和返回类型不一致先转成一致
309+ if ( count . GetType ( ) != resultType )
310+ constantCount = Expression . Convert ( constantCount , resultType ) ;
311+ var binaryExpression = Expression . Divide ( constantSum , constantCount ) ;
278312 var invoke = Expression . Lambda ( binaryExpression ) . Compile ( ) . DynamicInvoke ( ) ;
279313 return invoke ;
280314 }
@@ -284,29 +318,25 @@ public static object AverageWithCount(this IQueryable source, PropertyInfo avera
284318 /// <param name="source">数据源</param>
285319 /// <param name="averagePropertyName">聚合函数average属性名</param>
286320 /// <param name="sumPropertyName">聚合函数sum属性名</param>
321+ /// <param name="resultType">平均值返回结果:int/int=double</param>
287322 [ ExcludeFromCodeCoverage ]
288- public static object AverageWithSum ( this IQueryable source , string averagePropertyName , string sumPropertyName )
323+ public static object AverageWithSum ( this IQueryable source , string averagePropertyName , string sumPropertyName , Type resultType )
289324 {
290325 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
291326 if ( averagePropertyName == null ) throw new ArgumentNullException ( nameof ( averagePropertyName ) ) ;
292327 if ( sumPropertyName == null ) throw new ArgumentNullException ( nameof ( sumPropertyName ) ) ;
293328 var averageProperty = source . ElementType . GetProperty ( averagePropertyName ) ;
294329 var sumProperty = source . ElementType . GetProperty ( sumPropertyName ) ;
295- return source . AverageWithSum ( averageProperty , sumProperty ) ;
330+ return source . AverageWithSum ( averageProperty , sumProperty , resultType ) ;
296331 }
297- public static object AverageWithSum ( this IQueryable source , PropertyInfo averageProperty , PropertyInfo sumProperty )
332+ public static object AverageWithSum ( this IQueryable source , PropertyInfo averageProperty , PropertyInfo sumProperty , Type resultType )
298333 {
299334 if ( source == null ) throw new ArgumentNullException ( nameof ( source ) ) ;
300335 if ( averageProperty == null ) throw new ArgumentNullException ( nameof ( averageProperty ) ) ;
301336 if ( sumProperty == null ) throw new ArgumentNullException ( nameof ( sumProperty ) ) ;
302337 var count = source . AverageCount ( averageProperty , sumProperty ) ;
303- var sum = source . Sum ( sumProperty ) ;
304- var constantCount = Expression . Constant ( count ) ;
305- var constantSum = Expression . Constant ( sum ) ;
306- var unaryExpression = Expression . Convert ( constantCount , constantSum . GetType ( ) ) ;
307- var binaryExpression = Expression . Divide ( constantSum , unaryExpression ) ;
308- var invoke = Expression . Lambda ( binaryExpression ) . Compile ( ) . DynamicInvoke ( ) ;
309- return invoke ;
338+ var sum = source . SumByProperty ( sumProperty ) ;
339+ return AverageConstant ( sum , count , resultType ) ;
310340 }
311341 /// <summary>
312342 /// 获取平均数和 [{avg1,count1},{avg2,count2}....]=>sum(avg1...n*count1...n)/sum(count1...n)
0 commit comments