|
|
|
|
// Copyright (c) MudBlazor 2021
|
|
|
|
|
// MudBlazor licenses this file to you under the MIT license.
|
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
|
|
|
|
|
namespace Connected.Components;
|
|
|
|
|
|
|
|
|
|
public class AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
public AggregateType Type { get; set; } = AggregateType.Count;
|
|
|
|
|
public string DisplayFormat { get; set; } = "{value}";
|
|
|
|
|
public Func<IEnumerable<T>, string> CustomAggregate { get; set; }
|
|
|
|
|
|
|
|
|
|
private AggregateType? _cachedType;
|
|
|
|
|
private Func<T, decimal> _compiledAvgExpression;
|
|
|
|
|
private Func<T, object> _compiledMinMaxExpression;
|
|
|
|
|
private Func<T, decimal> _compiledSumExpression;
|
|
|
|
|
|
|
|
|
|
public string GetValue(string field, IEnumerable<T> items)
|
|
|
|
|
{
|
|
|
|
|
if (items == null || items.Count() == 0)
|
|
|
|
|
{
|
|
|
|
|
return DisplayFormat.Replace("{value}", "0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object value = null;
|
|
|
|
|
|
|
|
|
|
if (_cachedType != Type)
|
|
|
|
|
{
|
|
|
|
|
_cachedType = Type;
|
|
|
|
|
|
|
|
|
|
if (Type == AggregateType.Avg)
|
|
|
|
|
{
|
|
|
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
|
var f = Expression.Convert(Expression.Property(parameter, typeof(T).GetProperty(field)), typeof(decimal));
|
|
|
|
|
_compiledAvgExpression = Expression.Lambda<Func<T, decimal>>(f, parameter).Compile();
|
|
|
|
|
value = items.Average(_compiledAvgExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Count)
|
|
|
|
|
{
|
|
|
|
|
value = items.Count();
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Custom)
|
|
|
|
|
{
|
|
|
|
|
return CustomAggregate.Invoke(items);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Max)
|
|
|
|
|
{
|
|
|
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
|
var f = Expression.Convert(Expression.Property(parameter, typeof(T).GetProperty(field)), typeof(object));
|
|
|
|
|
_compiledMinMaxExpression = Expression.Lambda<Func<T, object>>(f, parameter).Compile();
|
|
|
|
|
value = items.Max(_compiledMinMaxExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Min)
|
|
|
|
|
{
|
|
|
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
|
var f = Expression.Convert(Expression.Property(parameter, typeof(T).GetProperty(field)), typeof(object));
|
|
|
|
|
_compiledMinMaxExpression = Expression.Lambda<Func<T, object>>(f, parameter).Compile();
|
|
|
|
|
value = items.Min(_compiledMinMaxExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Sum)
|
|
|
|
|
{
|
|
|
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
|
var f = Expression.Convert(Expression.Property(parameter, typeof(T).GetProperty(field)), typeof(decimal));
|
|
|
|
|
_compiledSumExpression = Expression.Lambda<Func<T, decimal>>(f, parameter).Compile();
|
|
|
|
|
value = items.Sum(_compiledSumExpression);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (Type == AggregateType.Avg)
|
|
|
|
|
{
|
|
|
|
|
value = items.Average(_compiledAvgExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Count)
|
|
|
|
|
{
|
|
|
|
|
value = items.Count();
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Custom)
|
|
|
|
|
{
|
|
|
|
|
return CustomAggregate.Invoke(items);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Max)
|
|
|
|
|
{
|
|
|
|
|
value = items.Max(_compiledMinMaxExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Min)
|
|
|
|
|
{
|
|
|
|
|
value = items.Min(_compiledMinMaxExpression);
|
|
|
|
|
}
|
|
|
|
|
else if (Type == AggregateType.Sum)
|
|
|
|
|
{
|
|
|
|
|
value = items.Sum(_compiledSumExpression);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DisplayFormat.Replace("{value}", (value ?? "").ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AggregateDefinition<T> SimpleAvg()
|
|
|
|
|
{
|
|
|
|
|
return new AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
Type = AggregateType.Avg,
|
|
|
|
|
DisplayFormat = "Average {value}"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AggregateDefinition<T> SimpleCount()
|
|
|
|
|
{
|
|
|
|
|
return new AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
Type = AggregateType.Count,
|
|
|
|
|
DisplayFormat = "Total {value}"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AggregateDefinition<T> SimpleMax()
|
|
|
|
|
{
|
|
|
|
|
return new AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
Type = AggregateType.Max,
|
|
|
|
|
DisplayFormat = "Max {value}"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AggregateDefinition<T> SimpleMin()
|
|
|
|
|
{
|
|
|
|
|
return new AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
Type = AggregateType.Min,
|
|
|
|
|
DisplayFormat = "Min {value}"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AggregateDefinition<T> SimpleSum()
|
|
|
|
|
{
|
|
|
|
|
return new AggregateDefinition<T>
|
|
|
|
|
{
|
|
|
|
|
Type = AggregateType.Sum,
|
|
|
|
|
DisplayFormat = "Sum {value}"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|