散列对象的快速方法专注于包含某个属性的属性?

Posted

技术标签:

【中文标题】散列对象的快速方法专注于包含某个属性的属性?【英文标题】:Fast way to hash objects focussing on properties containing a certain attribute? 【发布时间】: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。 【参考方案1】:

Unit Of Work 模式给了我一个想法。我完全删除了任何散列,并且对于我关心的特定属性属性,在它们的设置器中,我比较是否有任何东西从旧值更改为新值,如果有,我会增加一个计数器。没有散​​列的速度非常快。

    private void CompareChange<T>(T old, T newValue)
    
        if (!EqualityComparer<T>.Default.Equals(old, newValue))
            Interlocked.Increment(ref _ChangeCount);
    

【讨论】:

以上是关于散列对象的快速方法专注于包含某个属性的属性?的主要内容,如果未能解决你的问题,请参考以下文章

PHP中的OOP

PHP面向对象——1基础

缩小 UIScrollView 以专注于某个页面

从伪代码到科学方法论:专注于正事,不懈地实现自身价值,时不我待

PHP基础入门---PHP面向对象

面向对象的三大特征:继承 封装 多态