2

通常、テンプレート ファイルと実行するテキスト置換がある場合Dictionary<string,string>、次のようなを作成します。

Dictionary<string,string> substitutions = new Dictionary<string, string>
{
    {"{firstname}", customer.FirstName },
    {"{lastname}", customer.LastName },
    {"{address}", "your address" },
    {"{siteurl}", _siteUrl },
};

if (customer.Address != null)
{
    substitutions["{address}"] = customer.GetAddress();
}

等々。次に、次のようなことができます。

email.Body = substitutions.Aggregate(template,
    (current, sub) => current.Replace(sub.Key, sub.Value));

置換されたテンプレートを取得します。

今日、置換が特定の順序で実行されるようにする必要がある状況がありました。

これで、それらが正しい順序でに配置されていることを確認し、Dictionaryそれらが列挙される任意の順序がその順序を維持することを期待できます — aDictionaryが他の順序で列挙されるのを見たことはありませんが、 an の順序はそうでICollectionはありません保証します。

したがって、次のようなことを行うと便利だと思いました(i++「任意の値」のプレースホルダーとして使用されている場所:

SomeCollection<string,string,int> substitutions
    = new SomeCollection<string, string, int>
{
    {"{firstname}", customer.FirstName, i++ },
    {"{lastname}", customer.LastName, i++ },
    {"{address}", "your address", i++ },
    {"{siteurl}", _siteUrl, Int32.MaxValue }, // this should happen last
};

if (customer.Address != null)
{
    substitutions["{address}"] = customer.GetAddress();
}

IComparerそして、値を並べ替えるために何らかの種類の をプッシュすることができましたint

しかし、その後、そのようなコレクションを作成する方法を考え出そうとしましたDictionary<string, Tuple<int, string>>が、. on) を呼び出し.Replace("{siteurl}", _siteUrl)の最後に追加するだけで、Aggregate適切に機能します。

でも、エレガントにできたかもしれないものをあきらめてしまったのは、私を悩ませています。私が遭遇していた問題は(締め切りについてストレスを感じないようにしながら、 a を実装してメソッドを実装する方法を考え出すことを除いてDictionary<string, Tuple<int, string>>)、次のものが欲しいということでした:ICollection<KeyValuePair<string,string>>GetEnumerator

  • 上記のオブジェクト初期化構文を使用して簡単に宣言する機能。
  • キーでメンバーを取得および設定する機能 (したがって、 でバッキングDictionary<string, Tuple<int, string>>)。
  • foreachの順番でループを引き出す機能int
  • intアイテムのソート位置を気にしない場合、指定せずにアイテムを追加 (または初期化) する機能。
  • 上記の呼び出しのように、比較的簡潔なものを使用して置換を実行する機能Aggregate(おそらくIComparer、書き込みまでは取得できませんでした)。

私が行き詰まっていたのは、実装と、インデクサーのオーバーロードが難しくないことGetEnumeratorを忘れていたことです。

そのような要件をどのように実装しますか。私は正しい軌道に乗っていたのでしょうか、それとももっとエレガントなものを見落としていましたか? a に固執して、Dictionary<string,string>新しいアイテムを最初または最後に挿入する方法を考え出す必要がありますか?

私が完全に理解できなかった美​​しくエレガントなソリューションは何ですか? その必要をどのように満たしたでしょうか。

4

2 に答える 2

1

LINQ を使用して置換順序で並べ替えてから列挙できるようです。たとえば、 がある場合、次のDictionary<string, Tuple<string, int>>ようになります。

Dictionary<string, Tuple<string, int>> subs = new Dictionary<string, Tuple<string, int>>
{
    {"{firstname}", Tuple.Create(customer.FirstName, i++) },
    {"{lastname}", Tuple.Create(customer.LastName, i++) },
};

// Now order by substitution order
var ordered =
   from kvp in subs
   orderby kvp.Value.Item2
   select kvp;
foreach (var kvp in ordered)
{
    // apply substitution
}

ちなみに、Dictionary<TKey, TValue>列挙が追加された順序でアイテムを返すことを保証するものではありません。ある時点で注文を当てにしてやけどを負った覚えがあるようですが、それは他のコレクションクラスだったのかもしれません。いずれにせよ、文書化されていない動作を当てにすることは、何かがうまくいかないことを求めているだけです。

于 2013-02-07T19:35:52.377 に答える
0

.Net ディクショナリでエントリが加算されるのはなぜですか?

この質問は少し役立つかもしれません - 現在のバージョンの .NET で辞書のキーを反復すると、キーが順番に返されますが、これはコントラクトによって保証されていないため、.NET の将来のバージョンでは変更される可能性があります。これが気になる場合は、読み進めてください。そうでない場合は、辞書を反復処理します。

Dictionary<string, string>私の意見では、最も簡単な解決策は、あなたのアプローチに固執し、別のList<string> substitutionOrder. このリストを反復処理し、値を使用して辞書にインデックスを付けます。

email.Body = substitutionOrder.Aggregate(template,
    (current, sub) => current.Replace(substitutions[sub].Key, substitutions[sub].Value));
于 2013-02-07T19:12:53.807 に答える