3

ほぼ 200 のケースをテストする述語ハンドラーがあり、各テストには 5 つの可能な比較が含まれます。このコードを簡素化したいのですが、これを構文的に表現する方法に壁にぶつかっています。

public static Expression<Func<OADataConsolidated, bool>> Match(DOTSearchFilter filters)
{
    var predicate = (filters.OrFilters.Count > 0) ? PredicateBuilder.False<OADataConsolidated>() : PredicateBuilder.True<OADataConsolidated>();

    foreach (DOTFilter f in filters.AndFilters)
    {
        int value = -1;
        int.TryParse(f.TextValue, out value);
        switch (f.Type)
        {
            case DOTFilter.FilterType.SCO:
                switch (f.IdValue)
                {
                    case 4: // GED: Reasoning
                        switch (f.Comp)
                        {
                            case DOTFilter.Comparitor.LessThan:
                                predicate = predicate.And(p => p.ajblGEDR_Mean < value);
                                break;
                            case DOTFilter.Comparitor.EqualOrLess:
                                predicate = predicate.And(p => p.ajblGEDR_Mean <= value);
                                break;
                            case DOTFilter.Comparitor.EqualTo:
                                predicate = predicate.And(p => p.ajblGEDR_Mean == value);
                                break;
                            case DOTFilter.Comparitor.EqualOrGreater:
                                predicate = predicate.And(p => p.ajblGEDR_Mean >= value);
                                break;
                            case DOTFilter.Comparitor.GreaterThan:
                                predicate = predicate.And(p => p.ajblGEDR_Mean > value);
                                break;
                        }
                        break;
                    case 5: // GED: Mathematics
                        switch (f.Comp)
                        {
                            case DOTFilter.Comparitor.LessThan:
                                predicate = predicate.And(p => p.ajblGEDM < value);
                                break;
                            case DOTFilter.Comparitor.EqualOrLess:
                                predicate = predicate.And(p => p.ajblGEDM <= value);
                                break;
                            case DOTFilter.Comparitor.EqualTo:
                                predicate = predicate.And(p => p.ajblGEDM == value);
                                break;
                            case DOTFilter.Comparitor.EqualOrGreater:
                                predicate = predicate.And(p => p.ajblGEDM >= value);
                                break;
                            case DOTFilter.Comparitor.GreaterThan:
                                predicate = predicate.And(p => p.ajblGEDM > value);
                                break;
                        }
                        break;

上記の switch ステートメントはほぼ 200 回繰り返されますが、それぞれのケースで異なるのは、チェックされるフィールド名だけです。このコードをできるだけ減らしたい。

4

1 に答える 1

2

次のように式を動的に構築できます。

string propertyName = GetPropertyName(f);
ExpressionType comp = GetComparisonType(f);
ParameterExpression p = Expression.Parameter(typeof(OADataConsolidated));
Expression<Func<OADataConsolidated, bool>> expr =
    Expression.Lambda<Func<OADataConsolidated, bool>>(
        Expression.MakeBinary(
            comp,
            Expression.Property(p, propertyName),
            Expression.Constant((double)value)),
        p);

predicate = predicate.And(expr);


...

static string GetPropertyName(DOTFilter filter)
{
    switch(filter.IdValue)
    {
        case 4: // GED: Reasoning
            propertyName = "ajblGEDR_Mean";
            break;
        case 5: // GED: Mathematics
            propertyName = "ajblGEDM";
            break;
        ...
        default:
            throw new ArgumentException("Unknown Id value");
    }
}

static ExpressionType GetComparisonType(DOTFilter filter)
{
    switch (filter.Comp)
    {
        case DOTFilter.Comparitor.LessThan:
            return ExpressionType.LessThan;
        case DOTFilter.Comparitor.EqualOrLess:
            return ExpressionType.LessThanOrEqual;
        case DOTFilter.Comparitor.EqualTo:
            return ExpressionType.Equal;
        case DOTFilter.Comparitor.EqualOrGreater:
            return ExpressionType.GreaterThanOrEqual;
        case DOTFilter.Comparitor.GreaterThan:
            return ExpressionType.GreaterThan;
        default:
            throw new ArgumentException("Unknown Comp value");
    }
}

スイッチはまだありますが、繰り返されていません。

于 2012-07-30T22:49:13.110 に答える