2009-02-16 51 views
39

几乎每个程序员都会在他的生活中做过一次:如果变量的值发生变化,则设置一些标志。总是有很多的属性,你想跟踪某些东西在任何财产 实现“脏”标记功能的不同方法

  • 在一个特定的属性
  • 或在某些属性集合改变

    我感兴趣以不同的方式来实现上述情况下的“脏标志”功能,除了标准对象宽脏标志在每个属性更改上更新。必须有一些东西比在每个引用者中放入“dirty = true”:它看起来很丑并且是一件乏味的工作。

  • 回答

    24

    对于我的DAO,我保留了从数据库中检索的原始值的副本。当我发送它来更新时,我只是将原始值与当前值进行比较。它在处理上花费了一些成本,但比每个属性都有脏旗要好得多。

    编辑进一步证明没有脏标志:如果属性返回到它的原始值,没有办法反映,脏标志因为原始值丢失而继续脏。

    +1

    为什么它比每个属性都有脏标志好多了?你将更多的数据保存在内存中。我不是说你在做什么不好,但你没有理由。 – 2009-02-16 17:52:14

    +4

    如果你真的考虑过它,我不一定要在内存中保存更多的数据,因为我不需要为每个属性携带状态标志。如果数值恢复到原来的值,我不必担心将其设置回“不变”。另外肮脏的国旗不会让我回去。 – 2009-02-16 17:59:35

    +1

    我正在用我的DAO做同样的事情。这是很好的被证实! – MicSim 2009-02-16 18:59:49

    4

    我会把改变()在每个setter,即调用一个私人的方法,而不是只改变一个标志。然后该方法可以设置标志或做任何需要的处理,例如,它也可以通知任何观察员。

    6

    如果您正在设置一个“脏”标志意识到您正在保持状态。在某些情况下,你需要根据该状态采取行动,否则你不需要保持国旗。那么问题就变成了:是否有另一种触发所需行动的方式?发送某种消息?谁消耗“脏”状态并采取行动,并且是否有更清晰的通知界面?

    10

    我曾经有一个基本的实体类,提供脏/删除逻辑。

    当写实体-子类,你可以这样做:

    public string Name 
    { 
        get { return name; } 
        set { setValue("Name", value); } 
    } 
    

    这工作得很好,但有“丑陋的字符串”病......

    今天,你可以使用Lambda表达式来排除字符串:

    set {setValue(x => x.Name, value);} 
    

    或者说,我认为这是最好的解决方案,你可以使用AOP

    https://www.postsharp.net/

    这样,您可以通过属性定义操作。您创建一个属性并指定当用户更改关联的属性时,该实体变脏。

    此外,您可以保留您的班级(基本实体)中的属性列表,以记住更改后的属性,并从您的AOP代码中访问该列表。

    8

    我创建了一个名为DirtyValue<T>的类,它具有原始值和当前值。在第一次使用时,它会设置原始值和当前值。连续呼叫仅设置当前值。

    如果你可以告诉它通过比较两个改变,称为IsDirty只读布尔属性()。使用这种技术,您也可以访问原始值。

    5

    在有数据写入任务和独立的读取器任务某些情况下,我已经给每个任务updateCount变量。生产者在写入时增加其计数。只要读者醒来并发现其计数小于生产者数量,它就会使用当前值进行更新。你需要对计数器溢出进行一些特殊的处理,但这很容易实现。

    我已经成功地在模拟中使用了这种技术 - 生产者是物理循环,读者是3D显示器。

    2

    一个有趣的替代明确dirty=true的做法,尽管它可能是矫枉过正的大多数情况下,往往不适用,是使用防护页面。将内存页面设置为只读(例如在Windows上使用VirtualProtect()),并在程序尝试写入页面时捕获信号/异常。记录该页面已被修改,然后将页面的保护标志更改为可写并恢复执行。

    这通常是由操作系统以确定是否需要之前将其从RAM逐出将被写入到交换文件中的页面所采用的技术。

    -1

    你可能想看看重写的GetHashCode和等于你的域对象的方法和对象密钥存储在哈希表中原来的哈希码。然后创建一个接受对象的过程,在散列表中找到它的关键字并比较散列值。

    • 如果散列相同,没有变化。 (不发送到存储库或数据库)
    • 如果散列不同,对象有变化。 (更新)
    • 如果找不到密钥,对象是新的。 (插入)
    • 不知道如何确定是否需要删除对象,而不是根据请求删除进程而不使用哈希码跟踪。

    我还没有尝试过这一点,并且散列表可能不是跟踪对象键/散列值的最佳方式。它将通过仅跟踪哈希代码和密钥来保存mem。我不是100%确定的,但我认为一些orm可能会在他们的数据上下文/跟踪对象中使用这种方法。