Разбор пользовательских токенов данных и замена их значениями в C # - PullRequest
0 голосов
/ 07 мая 2011

У меня есть около 10 фрагментов данных из записи, и я хочу иметь возможность определить макет строки, в которую возвращаются эти данные, с возможностью пропустить некоторые фрагменты. Я думал о том, чтобы использовать enum для предоставления целочисленных значений моим токенам / полям, а затем иметь формат вроде {0}{1}{2}{3} или что-то более сложное, например {4} - {3}{1} [{8}]. Значение токенов относится к полям в моей базе данных. Например, у меня есть это перечисление для моих токенов, касающихся совершенных платежей.

AccountMask = 0,
AccountLast4 = 1,
AccountFirstDigit = 2,
AccountFirstLetter = 3,
ItemNumber = 4,
Amount = 5

Маска учетной записи - это строка типа VXXXXX1234, где V - для визы, а 1234 - последние 4 цифры карты. Иногда клиенты хотят V, иногда они хотят первую цифру (тип карты легко перевести в первую цифру).

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

Итак, для примера с использованием маски выше и моего перечисления, если я хочу определить формат 9{2}{1}{4:[0:0000000000]}

если номер позиции 678934

, который затем будет преобразован в 9412340000678934, где внутренняя часть токена 4 станет определением для String.Format этого значения. Кроме того, данные, размещенные вокруг токенов, игнорируются и сохраняются.

Моя проблема касается манипуляции со струной и лучшей практики. Мне сказали, что регулярные выражения могут быть дорогостоящими, если вы собираетесь создавать их на лету. Как мажор CS, я чувствую, что «правильное» (хотя и сложное) решение - создать лексер / парсер для моих токенов. У меня нет опыта написания лексера / синтаксического анализа в C #, поэтому я не уверен в лучших практиках вокруг него. Я ищу руководство по системе, которая эффективна и легко настраивается.

Ответы [ 2 ]

0 голосов
/ 19 мая 2011

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

var token = request.TokenFormat;

var matches = tokenExpression.Matches(request.TokenFormat);

foreach (Match match in matches)
{
    var value = match.Value;
    var tokenCode = (Token)Convert.ToInt32(value.Substring(1, (value.Contains(":") ? value.IndexOf(":") : value.IndexOf("}")) - 1));

    object data = null;

    switch (tokenCode)
    {
        case Token.AccountMask:
            data = accountMask;
            break;
        case Token.AccountLast4:
            data = accountMask.Substring(accountMask.Length - 4);
            break;
        case Token.AccountFirstDigit:
            string firstLetter = accountMask.Substring(0, 1);

            switch (firstLetter.ToUpper())
            {
                case "A":
                    data = 3;
                    break;
                case "V":
                    data = 4;
                    break;
                case "M":
                    data = 5;
                    break;
                case "D":
                    data = 6;
                    break;
            }

            break;
        case Token.AccountFirstLetter:
            data = accountMask.Substring(0, 1);
            break;
        case Token.ItemNumber:
            if(item != null)
                data = item.PaymentId;
            break;
        case Token.Amount:
            if (item != null)
                data = item.Amount;
            break;
        case Token.PaymentMethodId:
            if (paymentMethod != null)
                data = paymentMethod.PaymentMethodId;
            break;
    }

    if (formatExpression.IsMatch(value))
    {
        Match formatMatch = formatExpression.Match(value);
        string format = formatMatch.Value.Replace("[", "{").Replace("]", "}");

        token = token.Replace(value, String.Format(format, data));
    }
    else
    {
        token = token.Replace(value, String.Format("{0}", data));
    }
}

return token;
0 голосов
/ 07 мая 2011

Я вижу эту проблему, и я сразу подумал, что решение довольно простое;сохраните маски, которые вы хотите использовать, с постоянными значениями для различных полей данных, которые вы хотите включить, и передайте маски в постоянный вызов String.Format ():

const string CreditCardWithFirstLetterMask = "{3}XXXXXXXXXXX{1}";
const string CreditCardWithFirstDigitMask = "{2}XXXXXXXXXXX{1}";

...

var formattedString = String.Format(CreditCardWithFirstDigitMask, 
   record.AccountMask,
   record.AccountLast4,
   record.AccountFirstDigit,
   record.AccountFirstLetter,
   record.ItemNumber,
   record.Amount); 
...