我将使用ISO 3166-1国家/地区定义的示例。在标准中,您可能有3个值:alpha2国家/地区代码"CA"
,alpha3国家/地区代码"CAN"
和数字代码"040"
。所有这些都映射到国家Canada
。我无法使用外部数据源或随机加载文本文件。
我可以将它们存储在字典中,如下所示:
enum Country { Canada, UnitedStates };
void Main()
{
Dictionary<string, Country> countries = new Dictionary<string, Country>();
countries["CA"] = countries["CAN"] = countries["040"] = Country.Canada;
}
问题在于我必须为每个要添加的国家/地区添加一行。这就是要输入的很多国家/地区代码,以及要创建的很多枚举值。
似乎我想要做的是拥有一个&#34;代码内数据库&#34;编译到程序集中。一种选择是添加资源文件并每次解析文件,但这看起来太慢而且浪费。以二进制格式存储已解析的集合似乎很有吸引力。
如何为程序中的每个记录国家/地区存储这3个值以及完整的国家/地区名称?是否有一个逻辑和众所周知的设计模式来处理这个数据问题?
答案 0 :(得分:0)
在C#中,没有办法在编译图像中“预初始化”对象,就像使用C / C ++一样。这是因为编译的图像实际上并不是由执行的物理位组成,并且因为对象&amp; .NET Framework使用的类型系统使对象不仅仅是特定内存地址上的位排列 - 所有对象都具有vtable,可由GC重定位,并具有类型元数据。在文件中静态表示太多了。因此,任何在文件中 静态的对象都必须在加载时被“重新水化”,因此将原始位存储在简单编写代码以实例化对象上没有任何好处。
因此,这是您需要做的。有几种方法。一种是为数据提供简洁的文本格式,并在程序中将包含所有数据的字符串嵌入其中。然后,在静态构造函数中,一旦在应用程序启动时,您可以将该字符串解析为Dictionary<,>
以进行有效访问。
另一种方法是编写一个单独的应用程序,其目的是为您编写初始化代码 - “代码生成器”。然后,代码生成器以您可用的任何格式读取数据,然后吐出一大块C#代码,这些代码难以手动编写,并且容易出错,例如:
static readonly Dictionary<string, Country> CountriesByISOCode;
static Countries()
{
var countriesByISOCode = new Dictionary<string, Country>();
countriesByISOCode["AF"] = "Afghanistan";
countriesByISOCode["AFG"] = "Afghanistan";
countriesByISOCode["AL"] = "Albania";
countriesByISOCode["ALB"] = "Albania";
countriesByISOCode["DZ"] = "Algeria";
countriesByISOCode["DZA"] = "Algeria";
.
. // (about 475 more lines here, all written for you by the code generator)
.
Countries.CountriesByISOCode = countriesByISOCode;
}
然后,您可以自信地将该块复制/粘贴为静态初始化程序。
答案 1 :(得分:0)
使用资源文件并解析它听起来是您最好的选择。如果你
,它不会变得缓慢和浪费您可以从here获取要解析的CSV文件,这样您就不必在&#34;中键入它们。您可以使用this solution来解析它。这样做的主要优点是,您可以在文件发生变化时轻松更新文件。
即使您不同意这种方法最适合您,您也可以使用类似的代码来解析文件并使用它来生成初始化Dictionary的C#代码,以便您可以使用它来编译和编译准备&#34;
答案 2 :(得分:0)
是否存在处理此数据问题的逻辑和众所周知的设计模式?
如果我理解你正确地问了什么,这个问题基本上就是#34;是否存在一个通用的,众所周知的范例,用于程序从其自己编译的二进制文件中读取字节,然后将其用作数据在执行期间?&#34;
答案是否。 是可以完成的情况,但一般来说,你不能假设你可以做这样的事情,除非你知道可执行文件格式赢了&#39对你的操作系统中的程序加载器是否会锁定文件,阻止你对它进行读取等等,对一些随机字节的内容感到沮丧。