Использование лямбда-выражения, чтобы избежать использования «магической строки» для указания свойства - PullRequest
6 голосов
/ 25 июля 2010

Я пишу сервис, чтобы взять коллекцию объектов определенного типа и вывести его примитивные, строковые и DateTime типы в строку в CSV Format .У меня работают оба из следующих утверждений.Я считаю, что версия на основе лямбды намного чище.

Версия Magic String

string csv = new ToCsvService<DateTime>(objs)
    .Exclude("Minute")
    .ChangeName("Millisecond", "Milli")
    .Format("Date", "d")
    .ToCsv();

против.Лямбда-версия

string csv = new ToCsvService<DateTime>(objs)
    .Exclude(p => p.Minute)
    .ChangeName(p => p.Millisecond, "Milli")
    .Format(p => p.Date, "d")
    .ToCsv();

По рекомендации Джона Скита все лямбда-методы имеют одинаковую сигнатуру метода

public IToCsvService<T> Exclude<TResult>(
        Expression<Func<T, TResult>> expression)

Затем я передаю expression.Bodyдо FindMemberExpression.Я адаптировал код из FindMemberExpression метода ExpressionProcessor.cs из проекта nhlambdaextensions .Моя очень похожая версия FindMemberExpression приведена ниже:

private string FindMemberExpression(Expression expression)
{
    if (expression is MemberExpression)
    {
        MemberExpression memberExpression = (MemberExpression)expression;

        if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess
            || memberExpression.Expression.NodeType == ExpressionType.Call)
        {
            if (memberExpression.Member.DeclaringType.IsGenericType
                && memberExpression.Member.DeclaringType
                .GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if ("Value".Equals(memberExpression.Member.Name))
                {
                    return FindMemberExpression(memberExpression.Expression);
                }

                return String.Format("{0}.{1}",
                    FindMemberExpression(memberExpression.Expression),
                    memberExpression.Member.Name);
            }
        }
        else
        {
            return memberExpression.Member.Name;
        }
    }

    throw new Exception("Could not determine member from "
        + expression.ToString());
}

Я тестирую достаточно случаев в FindMemberExpression?Является ли то, что я делаю, излишним, учитывая мой вариант использования?

Ответы [ 2 ]

7 голосов
/ 25 июля 2010

РЕДАКТИРОВАТЬ: Ядро, чтобы сделать это проще, чтобы изменить сигнатуру ваших методов, чтобы быть универсальным и в типе результата:

public IToCsvService<TSource> Exclude<TResult>(
    Expression<Func<TSource, TResult>> expression)

Таким образом, вы не получите выражение преобразования, потому чтоконверсия не понадобится.Например, p => p.Minute в конечном итоге будет автоматически Expression<Func<DateTime, int>> из-за логического вывода типа.


Для меня это выглядит излишним, учитывая, что на данный момент все, что вам нужно, это свойство - по крайней мере,это все, что показывает ваш пример.

Почему бы не начать с простого распознавания свойства и расширить его позже , если вам нужно ?

РЕДАКТИРОВАТЬ:полный пример, который не показывает никаких преобразований:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main()
    {
        Expression<Func<DateTime, int>> dt = p => p.Minute;
        Console.WriteLine(dt);
    }
}

Однако, если вы измените тип выражения на Expression<Func<DateTime, long>>, он отобразит бит Convert(...).Я подозреваю, что вам нужно изменить сигнатуры ваших Exclude (и т. Д.) Методов.

4 голосов
/ 25 июля 2010

Есть ли у вас планы сделать его более гибким, или это все, что ему нужно сделать?

В идеале у вас должен быть самый простой код, который будет делать то, что вам нужно, чтобы вы могли уменьшить количество вещей, которые могут пойти не так.

Если вы делаете это как доказательство концепции и знаете, что позже вам понадобятся лямбда-выражения, то есть смысл их сохранить, но, если это конечный продукт, тогда первый легче прочитать и менее вероятно, будет причиной путаницы, если кому-то еще нужно внести изменения в код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...