开发者

How to check that I can SUM values of given type

In our application we have number of AggregatorTypes (idea copied from SQL Server) i.e. MinAggregator MaxAggregator, CountAggregator, And SumAggr开发者_如何学Pythonegator.

Now I should check if Aggregator supports type of provided values. For Count it is not important. For Max and Min I use checking for IComparable. But what to use for SUM? I tried Converter but it also supports string.

Why there is no ISummable :)

Also IsNumeric like checking is not a solution for me. For example TimeSpan also can sum.


Actually, for min/max it is easier to use Comparer<T>.Default, which also supports IComparable<T>, handles "lifted" operators, etc.

You can get most of this for free if you use MiscUtil; I wrote some code that provides access to generic operators, including generic extension methods for Sum, Average, etc. Unfortunately, operators can't appear on interfaces, and to make things worse the primitives don't actually have operators in the MethodInfo sense (this is provided directly in IL instead) - as discussed here.


Here is sample IsSummable method

public bool IsSummable(Type type)
try
{
  ParameterExpression paramA = Expression.Parameter(type, "a"), paramB = Expression.Parameter(type, "b");
  BinaryExpression addExpression = Expression.Add(paramA, paramB);
  var add = Expression.Lambda(addExpression, paramA, paramB).Compile();
  var v = Activator.CreateInstance(type);
  add.DynamicInvoke(v, v);
  return true;
}
catch
{
  return false;
}
}

and IsAveragable function (what a weird name:) )

public bool IsAveragable(Type type)
try
{
  ParameterExpression paramA = Expression.Parameter(type, "a"), paramB = Expression.Parameter(type, "b");
        // add the parameters together
        BinaryExpression addExpression = Expression.Add(paramA, paramB);
        var avg = Expression.Parameter(typeof(int), "b");
        var conv  = Expression.Convert(avg,type);
        BinaryExpression divideExpression = Expression.Divide(paramA, conv);
        // compile it
        var add = Expression.Lambda(addExpression, paramA, paramB).Compile();
        var divide = Expression.Lambda(divideExpression, paramA, avg).Compile();
        var v = Activator.CreateInstance(type);
        add.DynamicInvoke(v, v);
        divide.DynamicInvoke(v, 1);
                    return true;
}
catch
{
  return false;
}
}

part of the code taken from MiscUtil by Marc Gravell

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜