我正在试图找出代表某些数据的最佳方式。它基本上遵循表单Manufacturer.Product.Attribute = Value。类似的东西:
Acme。*。MinimumPrice = 100
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor =蓝色
因此除了产品A和B的情况外,所有Acme产品的最低价格是100。我想将这些数据存储在C#中并且具有GetValue(“Acme.ProductC.MinimumPrice”)返回100但GetValue的一些功能(“Acme.ProductA.MinimumPrice”)返回50。
我不确定如何最好地代表数据。有没有一种干净的方法来用C#编写代码?
编辑:我可能不太清楚。这是需要存储在文本文件中的配置数据,然后以某种方式解析并存储在内存中,以便像我给出的示例一样检索它。
答案 0 :(得分:2)
完全按照以下方式编写文本文件:
Acme.*.MinimumPrice = 100
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor = Blue
将其解析为路径/值对序列:
foreach (var pair in File.ReadAllLines(configFileName)
.Select(l => l.Split('='))
.Select(a => new { Path = a[0], Value = a[1] }))
{
// do something with each pair.Path and pair.Value
}
现在,有两种可能的解释,你想要做什么。字符串Acme.*.MinimumPrice
可能意味着对于没有特定覆盖的任何查找,例如Acme.Toadstool.MinimumPrice
,我们会返回100
- 即使在任何地方都没有引用Toadstool
的内容文件。或者它可能意味着如果文件中有100
的其他特定提及,它应该只返回Toadstool
。
如果它是前者,你可以将整个地段存储在一个扁平的字典中,并且在查找时间时不断尝试不同的密钥变体,直到找到匹配的东西。
如果是后者,则需要构建路径结构中实际出现的所有名称的数据结构,以避免返回实际不存在的名称的值。这对我来说似乎更可靠。
因此,使用后一个选项,Acme.*.MinimumPrice
实际上是在“将此MinimumPrice值添加到任何没有自己特定定义值的产品”。这意味着您基本上可以在分析时处理这些对以消除所有星号,将其扩展为相当于配置文件的完整版本:
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor = Blue
Acme.ProductC.MinimumPrice = 100
关于这一点的好处是你只需要一个平面字典作为最终表示,你可以使用TryGetValue
或[]
来查找。结果可能会更大,但这一切都取决于您的配置文件有多大。
你可以更少地存储信息,但我会选择一些简单易用的东西,然后给它一个非常简单的API,以便以后可以重新实现它。真的证明是必要的。您可能会发现(取决于应用程序)使查找过程更加复杂。
答案 1 :(得分:0)
我不完全确定你在问什么,但听起来你也在说。
除了两种情况外,我需要一个为每个产品ID返回固定值100的函数:ProductA和ProductB
在这种情况下,您甚至不需要数据结构。一个简单的比较函数就可以了
int GetValue(string key) {
if ( key == "Acme.ProductA.MinimumPrice" ) { return 50; }
else if (key == "Acme.ProductB.MinimumPrice") { return 60; }
else { return 100; }
}
或者你本来可以问
我需要一个函数,如果已经定义了将返回一个值,如果它不是
,则需要返回100
在这种情况下,我会使用Dictionary<string,int>
。例如
class DataBucket {
private Dictionary<string,int> _priceMap = new Dictionary<string,int>();
public DataBucket() {
_priceMap["Acme.ProductA.MinimumPrice"] = 50;
_priceMap["Acme.ProductB.MinimumPrice"] = 60;
}
public int GetValue(string key) {
int price = 0;
if ( !_priceMap.TryGetValue(key, out price)) {
price = 100;
}
return price;
}
}
答案 2 :(得分:0)
其中一种方法 - 您可以创建嵌套字典:Dictionary<string, Dictionary<string, Dictionary<string, object>>>
。在您的代码中,您应该按点分割“Acme.ProductA.MinimumPrice”,并获取或设置与分割块对应的字典的值。
另一种方法是使用Linq2Xml:您可以使用Acme作为根节点创建XDocument
,将产品创建为根的子项,并将属性实际存储为产品或子节点上的属性。我更喜欢第二种解决方案,但如果您有数千种产品,它会更慢。
答案 3 :(得分:0)
我会采用OOP方法。您解释它的方式是所有产品都由对象表示,这很好。这似乎很好地利用了多态性。
我希望所有产品都有一个ProductBase,其默认属性为
virtual MinimumPrice { get { return 100; } }
然后,您的特定产品(例如ProductA)将覆盖功能:
override MinimumPrice { get { return 50; } }