如何创建确定性指导

在我们的应用程序中,我们正在创建具有Guid值的属性的Xml文件。 这个值需要在文件升级之间保持一致。 因此,即使文件中的其他内容发生更改,该属性的guid值也应保持不变。

一个明显的解决方案是创建一个带有文件名和Guid的静态字典用于他们。 然后,无论何时生成文件,我们都会查找字典中的文件名并使用相应的guid。 但这是不可行的,因为我们可能扩展到100个文件,并且不想维护大量的guid。

所以另一种方法是根据文件的路径使Guid相同。 由于我们的文件路径和应用程序目录结构是唯一的,因此Guid对于该路径应该是唯一的。 因此,每次我们运行升级时,文件都会根据其路径获取相同的GUID。 我发现了一种很酷的方式来生成这样的“确定性指导”(感谢埃尔顿斯通曼)。 它基本上这样做:

private Guid GetDeterministicGuid(string input) 

{ 

//use MD5 hash to get a 16-byte hash of the string: 

MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider(); 

byte[] inputBytes = Encoding.Default.GetBytes(input); 

byte[] hashBytes = provider.ComputeHash(inputBytes); 

//generate a guid from the hash: 

Guid hashGuid = new Guid(hashBytes); 

return hashGuid; 

} 

所以给一个字符串,Guid将永远是一样的。

有没有其他方法或建议的方法来做到这一点? 该方法的优点或缺点是什么?


正如@bacar所述,RFC 4122§4.3定义了一种创建基于名称的UUID的方法。 这样做的好处(仅仅使用MD5散列)就是保证不会与非基于命名的UUID发生冲突,并且与其他基于名称的UUID发生冲突的可能性很小(非常小)。

.NET Framework中没有用于创建这些内容的本机支持,但是我在GitHub上发布了实现该算法的代码。 它可以使用如下:

Guid guid = GuidUtility.Create(GuidUtility.UrlNamespace, filePath);

为了进一步降低与其他GUID冲突的风险,您可以创建一个专用GUID作为名称空间ID(而不是使用RFC中定义的URL名称空间ID)。


这会将任何字符串转换为Guid,而无需导入外部程序集。

public static Guid ToGuid(string src)
{
    byte[] stringbytes = Encoding.UTF8.GetBytes(src);
    byte[] hashedBytes = new System.Security.Cryptography
        .SHA1CryptoServiceProvider()
        .ComputeHash(stringbytes);
    Array.Resize(ref hashedBytes, 16);
    return new Guid(hashedBytes);
}

有更好的方法来生成一个独特的Guid,但这是一种将字符串数据密钥持续升级为Guid数据密钥的方法。


正如Rob提到的,你的方法不会生成UUID,它会生成一个看起来像UUID的哈希。

UUID上的RFC 4122特别允许确定性(基于名称的)UUID - 版本3和版本5分别使用md5和SHA1。 大多数人可能熟悉版本4,这是随机的。 维基百科对这些版本进行了很好的概述。 (请注意,这里使用'version'这个词似乎是描述了UUID的'类型' - 版本5没有取代版本4)。

似乎有一些库用于生成版本3/5的UUID,包括python uuid模块,boost.uuid(C ++)和OSSP UUID。 (我没有找过任何.net的)

链接地址: http://www.djcxy.com/p/91467.html

上一篇: How to Create Deterministic Guids

下一篇: What is the string length of a GUID?