【发布时间】:2013-07-24 15:52:04
【问题描述】:
我创建了我自己的序列化形式,它将提供的对象转换为字符串,然后我可以获得 MD5 哈希值。散列用于快速比较以查看特定属性是否已更改。但是我的代码非常慢,我想知道是否有人有更好的想法?
我需要只担心标有自定义 [DatabaseMap] 属性的对象中的属性。我不太关心哈希方法,而是对象在被哈希之前序列化的方式。
有更好的方法吗?
public static string GetHash(this IBaseObject source)
{
if (source == null)
return string.Empty;
// step 1, calculate MD5 hash from input
var hasher = new ThreadLocal<MD5>(MD5.Create);
byte[] inputBytes = Encoding.UTF8.GetBytes(SerializeDataMembers(source, hasher)); // serialize the object
byte[] hash = hasher.Value.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < hash.Length; i++)
// {
// sb.Append(hash[i].ToString("X2"));
// }
// return sb.ToString();
return BitConverter.ToString(hash);
}
private static string SerializeDataMembers(IBaseObject source, MD5 hasher)
{
StringBuilder sb = new StringBuilder();
var properties = source.GetType().GetProperties();
foreach (PropertyInfo prop in properties)
{
var attrs = Attribute.GetCustomAttributes(prop);
if (attrs.OfType<DatabaseMap>().Any())
{
if (prop.PropertyType == typeof (byte[]))
{
sb.Append(Convert.ToBase64String(hasher.ComputeHash((byte[])prop.GetValue(source))));
}
else
{
sb.Append(prop.GetValue(source));
}
}
}
return sb.ToString();
}
【问题讨论】:
-
既然可以override GetHashCode,为什么还要麻烦MD5比较对象。
-
我需要一种快速的方法来散列一个对象,然后再生成一个散列来查看是否有任何标记为特定属性的属性已被更改。我最初使用 ServiceStack.Text 序列化对象,但是这会序列化整个对象,而我只关心某些属性。然后我想出了上面的解决方案,但我相信有更快的方法。哈希方法不是问题。
-
我认为正确的做法是为您的接口实现一个
IComparer(T)以获取属性。 -
但我不是在比较两个对象。用例是在初始化对象时我对其进行哈希处理 - 稍后当有人想要将对象提交到数据存储时,会创建另一个哈希(在同一对象上),然后与原始哈希进行比较。如果这些哈希值不同,则提交发生,否则由于没有进行任何更改,因此什么也不会发生。
-
你所描述的类似于Unit Of Work pattern。
标签: c# serialization hash md5