几乎每个程序员一生都做过一次:如果变量的值发生变化,设置一些标志。总是有很多属性,如果发生了变化,你想跟踪
我对以上情况实现“脏标志”功能的不同方式感兴趣,除了在每次属性更改时更新标准对象范围的脏标志。必须有比在每个setter中放置“dirty = true”更好的东西:它看起来很丑陋而且是一项繁琐的工作。
答案 0 :(得分:24)
对于我的DAO,我保留了从数据库中检索到的原始值的副本。当我发送它进行更新时,我只是将原始值与当前值进行比较。它的处理成本稍高,但它比每个属性都有一个脏标志要好得多。
编辑以进一步证明没有脏标志:如果属性返回其原始值,则无法反映出来,脏标志会继续变脏,因为原始值已丢失。
答案 1 :(得分:10)
我曾经有一个基本的Entity类,提供了Dirty / Removed Logic。
编写实体子类时,可以执行以下操作:
public string Name
{
get { return name; }
set { setValue("Name", value); }
}
这种方法很好,但有“丑陋的字符串”疾病......
今天你可以使用Lambda表达式来排除字符串:
set {setValue(x => x.Name, value);}
或者,我认为这是最好的解决方案,您可以使用AOP:
这样,您可以按属性定义操作。您创建一个属性并指定当用户更改关联属性时,该实体变脏。
此外,您可以在您的类(基本实体)中保留一个属性列表,它将记住更改的属性,并从您的AOP代码访问该列表。
答案 2 :(得分:8)
我创建了一个名为DirtyValue<T>
的类,它有一个原始值和一个当前值。首次使用时,它会设置原始值和当前值。连续调用仅设置当前值。
你可以通过比较两者来判断它是否已经改变了,只有一个名为IsDirty()的readonly bool属性。使用这种技术,您也可以访问原始值。
答案 3 :(得分:6)
如果您设置“脏”标志,则意识到您保持状态。在某些时候,您需要根据该状态采取行动,否则您不需要保留该标志。那么问题就变成了:是否还有另一种触发所需行动的方法?发送某种消息?谁消耗“脏”状态并采取行动,是否有更清晰的通知接口?
答案 4 :(得分:5)
在某些具有数据编写器任务和独立读者任务的情况下,我给每个任务一个updateCount
变量。生成器在写入时递增其计数。每当读者醒来并发现其计数小于生产者的计数时,它会使用当前值进行更新。您需要对计数器溢出进行一些特殊处理,但实现起来非常简单。
我在模拟中成功地使用了这种技术 - 生产者是物理循环而读者是3d显示器。
答案 5 :(得分:4)
我会在每个setter中放置changed(),即调用私有方法而不是仅仅更改标志。然后,该方法可以设置标志或进行任何需要的处理,例如,它也可以通知任何观察员。
答案 6 :(得分:2)
显式dirty=true
方法的一个有趣的替代方法,虽然在大多数情况下可能是过度杀戮,而且通常不适用,但是使用保护页面。将内存页面设置为只读(例如,在Windows上使用VirtualProtect())并在程序尝试写入页面时捕获信号/异常。记录页面已被修改,然后将页面的保护标志更改为可写并继续执行。
这是操作系统通常采用的技术,用于确定页面是否需要在从RAM中逐出之前写入交换文件。
答案 7 :(得分:-1)
您可能希望查看覆盖域对象的gethashcode和equals方法,并按对象键将原始哈希码存储在哈希表中。然后创建一个进程,该进程接受一个对象,在哈希表中找到它的键并比较哈希值。
我没有尝试过这个,哈希表可能不是跟踪对象键/哈希值的最佳方法。它只会通过跟踪哈希码和密钥来保存mem。我不是百分百肯定,但我认为一些orm可能会在他们的数据上下文/跟踪对象中使用此方法。