是否可以将 Enumerable.Sum() 扩展与动态类型一起使用

本文关键字:动态 类型 一起 扩展 Enumerable Sum 是否 | 更新日期: 2023-09-27 18:33:53

在我的项目中,我正在使用Telerik RadGridView控件,其ItemSource是动态对象列表(派生自DynamicObject)。
我计划使用AggregateFunctions,如SumFunction,MinFunction,但它在列中崩溃,这些列从动态属性中获取值。如果我是对的,那是因为Linq扩展,而不是Telerik。
此问题是否有任何解决方法?

更新
模型类如下所示

public class SampleModel : DynamicObject
{
   // some properties
}   

来源如下:

 myGrid.ItemsSource = new List<SampleModel> { // some model items };

XAML 是:

<telerik:RadGridView ShowColumnFooters="True" AutoGenerateColumns="False" x:Name="myGrid">
        <telerik:RadGridView.Columns>
            <telerik:GridViewDataColumn DataMemberBinding="{Binding p1}">
                <telerik:GridViewDataColumn.AggregateFunctions>
                    <telerik:SumFunction />
                </telerik:GridViewDataColumn.AggregateFunctions>
            </telerik:GridViewDataColumn>
        </telerik:RadGridView.Columns>
    </telerik:RadGridView>

其中 p1 是动态属性
异常消息为:
类型"System.Linq.Enumerable"上没有泛型方法"Sum"与提供的类型参数和参数兼容。如果该方法是非泛型的,则不应提供类型参数。

是否可以将 Enumerable.Sum() 扩展与动态类型一起使用

我通过创建自己的聚合函数并在其中手动构建表达式来解决此问题(来源:Telerik 支持)。
Sum() 函数的代码是:

public class CustomSumFunction : EnumerableSelectorAggregateFunction
{
    protected override string AggregateMethodName
    {
        get { return "Sum"; }
    }
    protected override Type ExtensionMethodsType
    {
        get
        {
            return typeof(CustomAggregateFunctions);
        }
    }
}
public static class CustomAggregateFunctions
{
    public static TValue Sum<T, TValue>(IEnumerable<T> source, Func<T, TValue> selector)
    {
        return source.Select(selector).Aggregate((t1, t2) => 
            {
                Expression expr = Expression.Add(Expression.Constant(t1, t1.GetType()), Expression.Constant(t2, t2.GetType()));
                Expression conversion = Expression.Convert(expr, typeof(TValue));
                return Expression.Lambda<Func<TValue>>(conversion).Compile()();                    
            });
    }
    public static decimal? Sum<TSource>(IEnumerable<TSource> source, Func<TSource, decimal?> selector)
    {
        return source.Sum(selector);
    }
    public static decimal Sum<TSource>(IEnumerable<TSource> source, Func<TSource, decimal> selector)
    {
        return source.Sum(selector);
    }
    public static double? Sum<TSource>(IEnumerable<TSource> source, Func<TSource, double?> selector)
    {
        return source.Sum(selector);
    }
    public static double Sum<TSource>(IEnumerable<TSource> source, Func<TSource, double> selector)
    {
        return source.Sum(selector);
    }
    public static float? Sum<TSource>(IEnumerable<TSource> source, Func<TSource, float?> selector)
    {
        return source.Sum(selector);
    }
    public static float Sum<TSource>(IEnumerable<TSource> source, Func<TSource, float> selector)
    {
        return source.Sum(selector);
    }
    public static int? Sum<TSource>(IEnumerable<TSource> source, Func<TSource, int?> selector)
    {
        return source.Sum(selector);
    }
    public static int Sum<TSource>(IEnumerable<TSource> source, Func<TSource, int> selector)
    {
        return source.Sum(selector);
    }
    public static long? Sum<TSource>(IEnumerable<TSource> source, Func<TSource, long?> selector)
    {
        return source.Sum(selector);
    }
    public static long Sum<TSource>(IEnumerable<TSource> source, Func<TSource, long> selector)
    {
        return source.Sum(selector);
    }
}