几乎每个程序员都会在他的生活中做过一次:如果变量的值发生变化,则设置一些标志。总是有很多的属性,你想跟踪某些东西在任何财产 实现“脏”标记功能的不同方法
我感兴趣以不同的方式来实现上述情况下的“脏标志”功能,除了标准对象宽脏标志在每个属性更改上更新。必须有一些东西比在每个引用者中放入“dirty = true”:它看起来很丑并且是一件乏味的工作。
几乎每个程序员都会在他的生活中做过一次:如果变量的值发生变化,则设置一些标志。总是有很多的属性,你想跟踪某些东西在任何财产 实现“脏”标记功能的不同方法
我感兴趣以不同的方式来实现上述情况下的“脏标志”功能,除了标准对象宽脏标志在每个属性更改上更新。必须有一些东西比在每个引用者中放入“dirty = true”:它看起来很丑并且是一件乏味的工作。
对于我的DAO,我保留了从数据库中检索的原始值的副本。当我发送它来更新时,我只是将原始值与当前值进行比较。它在处理上花费了一些成本,但比每个属性都有脏旗要好得多。
编辑进一步证明没有脏标志:如果属性返回到它的原始值,没有办法反映,脏标志因为原始值丢失而继续脏。
我会把改变()在每个setter,即调用一个私人的方法,而不是只改变一个标志。然后该方法可以设置标志或做任何需要的处理,例如,它也可以通知任何观察员。
如果您正在设置一个“脏”标志意识到您正在保持状态。在某些情况下,你需要根据该状态采取行动,否则你不需要保持国旗。那么问题就变成了:是否有另一种触发所需行动的方式?发送某种消息?谁消耗“脏”状态并采取行动,并且是否有更清晰的通知界面?
我曾经有一个基本的实体类,提供脏/删除逻辑。
当写实体-子类,你可以这样做:
public string Name
{
get { return name; }
set { setValue("Name", value); }
}
这工作得很好,但有“丑陋的字符串”病......
今天,你可以使用Lambda表达式来排除字符串:
set {setValue(x => x.Name, value);}
或者说,我认为这是最好的解决方案,你可以使用AOP:
这样,您可以通过属性定义操作。您创建一个属性并指定当用户更改关联的属性时,该实体变脏。
此外,您可以保留您的班级(基本实体)中的属性列表,以记住更改后的属性,并从您的AOP代码中访问该列表。
我创建了一个名为DirtyValue<T>
的类,它具有原始值和当前值。在第一次使用时,它会设置原始值和当前值。连续呼叫仅设置当前值。
如果你可以告诉它通过比较两个改变,称为IsDirty只读布尔属性()。使用这种技术,您也可以访问原始值。
在有数据写入任务和独立的读取器任务某些情况下,我已经给每个任务updateCount
变量。生产者在写入时增加其计数。只要读者醒来并发现其计数小于生产者数量,它就会使用当前值进行更新。你需要对计数器溢出进行一些特殊的处理,但这很容易实现。
我已经成功地在模拟中使用了这种技术 - 生产者是物理循环,读者是3D显示器。
一个有趣的替代明确dirty=true
的做法,尽管它可能是矫枉过正的大多数情况下,往往不适用,是使用防护页面。将内存页面设置为只读(例如在Windows上使用VirtualProtect()),并在程序尝试写入页面时捕获信号/异常。记录该页面已被修改,然后将页面的保护标志更改为可写并恢复执行。
这通常是由操作系统以确定是否需要之前将其从RAM逐出将被写入到交换文件中的页面所采用的技术。
你可能想看看重写的GetHashCode和等于你的域对象的方法和对象密钥存储在哈希表中原来的哈希码。然后创建一个接受对象的过程,在散列表中找到它的关键字并比较散列值。
我还没有尝试过这一点,并且散列表可能不是跟踪对象键/散列值的最佳方式。它将通过仅跟踪哈希代码和密钥来保存mem。我不是100%确定的,但我认为一些orm可能会在他们的数据上下文/跟踪对象中使用这种方法。
为什么它比每个属性都有脏标志好多了?你将更多的数据保存在内存中。我不是说你在做什么不好,但你没有理由。 – 2009-02-16 17:52:14
如果你真的考虑过它,我不一定要在内存中保存更多的数据,因为我不需要为每个属性携带状态标志。如果数值恢复到原来的值,我不必担心将其设置回“不变”。另外肮脏的国旗不会让我回去。 – 2009-02-16 17:59:35
我正在用我的DAO做同样的事情。这是很好的被证实! – MicSim 2009-02-16 18:59:49