通常,当我们有一个模板文件和一些文本替换来运行时,我们创建一个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
并希望它们所列举的任意顺序保持这个序列 - 我从未见过Dictionary
在其他一些序列中枚举,但不保证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>>
支持的东西后,我决定我的代码的优雅不值得它的压力。导致我(截止日期等)我可以将.Replace("{siteurl}", _siteUrl)
添加到Aggregate
电话的末尾,这样就可以充分发挥作用。
但令我烦恼的是,我已经放弃了本来可能是一件优雅的事情。我遇到的问题(除了试图纠缠Dictionary<string, Tuple<int, string>>
作为ICollection<KeyValuePair<string,string>>
的实现,并试图实现GetEnumerator
方法,同时尽量不强调截止日期)我想要以下内容:
Dictionary<string, Tuple<int, string>>
支持)。foreach
圈的功能可以按int
的顺序排除。int
的情况下添加(或初始化)项目。Aggregate
调用(可能传递IComparer
我没有达到写作的目的)。我遇到的问题是GetEnumerator
实施,而我未能记住indexer overloading并不困难。
您将如何实施此类要求。我是在正确的轨道上还是忽略了更优雅的东西?我是否应该坚持使用Dictionary<string,string>
并想出一些方法在开始或结束时插入新项目 - 或者如果我不关心该项目那么只是中间位置?
我还没有达到什么美丽,优雅的解决方案?你将如何满足这种需求?
答案 0 :(得分: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>
并不保证枚举会按照添加顺序返回项目。我似乎记得在某些时候通过指望顺序而被烧毁,但它可能是其他一些集合类。在任何情况下,依靠无证件行为只是要求出错。
答案 1 :(得分:0)
Why are entries in addition order in a .Net Dictionary?
这个问题可能对你有所帮助 - 在当前版本的.NET中迭代字典的密钥将按顺序返回密钥,但由于合同无法保证这一点,因此在未来的.NET版本中可能会有所改变。如果这让您担心,请继续阅读。如果没有,只需迭代字典。
在我看来,最简单的解决方案是坚持使用Dictionary<string, string>
方法并保持单独的List<string> substitutionOrder
。迭代此列表,并使用这些值索引到您的字典中。
email.Body = substitutionOrder.Aggregate(template,
(current, sub) => current.Replace(substitutions[sub].Key, substitutions[sub].Value));