是否可以对动态类型使用Enumerable.Sum()扩展?

时间:2013-10-03 20:16:14

标签: c# linq dynamic telerik

在我的项目中,我使用Telerik RadGridView控件,其中ItemSource是动态对象列表(从DynamicObject派生)。
我计划使用像SumFunction,MinFunction这样的AggregateFunctions,但它在列中崩溃,这些列从动态属性获取值。如果我是正确的,那是因为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'与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

1 个答案:

答案 0 :(得分:2)

我通过创建自己的聚合函数并在其中手动构建表达式来解决了这个问题(来源:Telerik support)。
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);
    }
}