public override Expression BuildExpression(ParameterExpression paramExpression) { // Get underlying type of IEnumerable if (!paramExpression.Type.GetInterfaces().Contains(typeof(IEnumerable))) { throw new Exception($"DataContext (paramExpression: {paramExpression.Type.ToString()}) must implement IEnumerable. Where apply over IEnumerable<T>"); } if (paramExpression.Type.GenericTypeArguments.Length == 0) { throw new Exception($"DataContext (paramExpression: {paramExpression.Type.ToString()}) must have one generic parameter: IEnumerable<T>"); } Type underlyingTypeList = paramExpression.Type.GenericTypeArguments.First(); Type ienumerableType = typeof(IEnumerable <>).MakeGenericType(underlyingTypeList); MethodInfo firstMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.FirstOrDefault), new[] { underlyingTypeList }, new[] { ienumerableType }, BindingFlags.Static);; Expression firstExpression = Expression.Call(firstMethod, paramExpression); Expression propertyExpression = Expression.Property(firstExpression, SelectedProperty); // Check types Type internalType = new TPrimitiveType().InternalType; if (propertyExpression.Type != internalType) { return(Expression.Convert(propertyExpression, internalType)); } else { return(propertyExpression); } }
public override Expression BuildExpression(ParameterExpression paramExpression) { // Extract underlying type of List Type underlyingTypeList = paramExpression.Type.GenericTypeArguments.First(); // Create a new parameter ParameterExpression newParameter = Expression.Parameter(underlyingTypeList, "newParameter"); // Create generic IEnumerable<> Type ienumerableType = typeof(IEnumerable <>).MakeGenericType(underlyingTypeList); // Count() MethodInfo countMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.Count), new[] { underlyingTypeList }, new[] { ienumerableType }, BindingFlags.Static); return(Expression.Convert(Expression.Call(countMethod, paramExpression), typeof(double))); // Auto conversion to double }
public override Expression BuildExpression(ParameterExpression paramExpression) { // Extract underlying type of List Type underlyingTypeList = paramExpression.Type.GenericTypeArguments.First(); // Create a new parameter ParameterExpression newParameter = Expression.Parameter(underlyingTypeList, "p"); // Create generic IEnumerable<> Type ienumerableType = typeof(IEnumerable <>).MakeGenericType(underlyingTypeList); MethodInfo geoMethod = GetType().GetMethod(nameof(GetGeometricMean), BindingFlags.NonPublic | BindingFlags.Static); Expression geoExpression = null; if (!string.IsNullOrEmpty(SelectedProperty)) { // Geo(p => p.selectedProperty) Type propertyType = ClassMetadataLocator.GetPropertyType(underlyingTypeList, SelectedProperty); Type funcType = typeof(Func <,>).MakeGenericType(underlyingTypeList, propertyType); // Proyección Select Expression selectExpression = Expression.Lambda(Expression.Property(newParameter, SelectedProperty), newParameter); MethodInfo selectMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.Select), new[] { underlyingTypeList, propertyType }, new[] { ienumerableType, funcType }, BindingFlags.Static); Expression projectionExpression = Expression.Call(selectMethod, paramExpression, selectExpression); geoExpression = Expression.Call(geoMethod, projectionExpression); } else { // Geo(IEnumerable<PrimitiveType>) geoExpression = Expression.Call(geoMethod, paramExpression); } Type internalType = new TArithmeticType().InternalType; if (geoExpression.Type != internalType) { return(Expression.Convert(geoExpression, internalType)); } return(geoExpression); }
public override Expression BuildExpression(ParameterExpression paramExpression) { // Extract underlying type of List Type underlyingTypeList = paramExpression.Type.GenericTypeArguments.First(); // Create a new parameter ParameterExpression newParameter = Expression.Parameter(underlyingTypeList, "newParameter"); // Create generic IEnumerable<> Type iEnumerableType = typeof(IEnumerable <>).MakeGenericType(underlyingTypeList); Expression avgExpression = null; if (!string.IsNullOrEmpty(SelectedProperty)) { // Avg(p => p.NombrePropiedad) Type propertyType = ClassMetadataLocator.GetPropertyType(underlyingTypeList, SelectedProperty); Type funcType = typeof(Func <,>).MakeGenericType(underlyingTypeList, propertyType); MethodInfo averageMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.Average), new[] { underlyingTypeList }, new[] { iEnumerableType, funcType }, BindingFlags.Static); Expression propertyProjection = Expression.Lambda(Expression.Property(newParameter, SelectedProperty), newParameter); avgExpression = Expression.Call(averageMethod, paramExpression, propertyProjection); } else { // Avg(IEnumerable<PrimitiveType>) MethodInfo avgMethod = typeof(Enumerable).GetMethods().Single(m => m.Name == nameof(Enumerable.Average) && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == iEnumerableType); avgExpression = Expression.Call(avgMethod, paramExpression); } Type internalType = new TArithmeticType().InternalType; if (avgExpression.Type != internalType) { return(Expression.Convert(avgExpression, internalType)); } return(avgExpression); }
public override Expression BuildExpression(ParameterExpression paramExpression) { ParameterExpression paramExpressionI = Expression.Parameter(typeof(string), "i"); ParameterExpression paramExpressionJ = Expression.Parameter(typeof(string), "j"); MethodInfo stringConcat = typeof(string).GetMethod(nameof(string.Concat), new Type[] { typeof(string), typeof(string), typeof(string) }); // Concatenación Expression concatExpression = Expression.Call(stringConcat, paramExpressionI, Expression.Constant(Delimiter), paramExpressionJ); Type ienumerableType = typeof(IEnumerable <>).MakeGenericType(typeof(string)); Type funcType = typeof(Func <, ,>).MakeGenericType(typeof(string), typeof(string), typeof(string)); // public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func) MethodInfo aggregateMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.Aggregate), new[] { typeof(string) }, new[] { ienumerableType, funcType }, BindingFlags.Static); // Select // public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector); Type underlyingTypeList = paramExpression.Type.GenericTypeArguments.First(); ParameterExpression newParameter = Expression.Parameter(underlyingTypeList, "newParameter"); Expression selectExpression = Expression.Lambda(Expression.Property(newParameter, SelectedProperty), newParameter); MethodInfo selectMethod = (MethodInfo)ClassMetadataLocator.GetGenericMethod(typeof(Enumerable), nameof(Enumerable.Select), new[] { underlyingTypeList, typeof(string) }, new[] { paramExpression.Type, typeof(Func <,>).MakeGenericType(underlyingTypeList, typeof(string)) }, BindingFlags.Static); Expression projection = Expression.Call(selectMethod, paramExpression, selectExpression); return(Expression.Call(aggregateMethod, projection, Expression.Lambda(concatExpression, paramExpressionI, paramExpressionJ))); }