0

レコードから約 10 個のデータがあり、このデータが返される文字列のレイアウトを定義できるようにしたいと考えています。いくつかの部分を除外するオプションがあります。私の考えは、列挙型を使用してトークン/フィールドに整数値を与え、次のような形式{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その値の a の定義になります。また、トークンの周囲に配置されたデータは無視され、所定の位置に保持されます。

私の問題は、文字列の操作とベストプラクティスです。正規表現をその場で作成しようとすると、コストがかかる可能性があると言われています。CS専攻として、「正しい」(どんなに複雑な) 解決策は、自分のトークン用のレクサー/パーサーを作成することだと感じています。私は C# でレクサー/パースを書いた経験がないので、その周りのベスト プラクティスがわかりません。ここでは、効率的で簡単に調整できるシステムに関するガイダンスを探しています。

4

2 に答える 2

0

最終的に、正規表現を静的オブジェクトとしてクラスに配置し、一致をループして置換を実行し、トークンを構築しました。

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;
于 2011-05-19T14:55:31.083 に答える
0

私はこの問題を見て、解決策は非常に簡単だとすぐに思いました。使用したいマスクを、含めたいさまざまなデータ フィールドの定数値とともに保存し、そのマスクを 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); 
于 2011-05-06T20:40:35.243 に答える