C#:有没有办法轻松查找/更新对象的所有引用?

时间:2010-02-27 23:47:03

标签: c# .net reference garbage-collection

我一直在阅读Rockford Lhotka的“Expert C#2008 Business Objects”,其中有一个数据门户网站可以很好地抽象出数据的来源。当使用DataPortal.Update(this)时,正如您可能猜测的那样,将“this”持久存储到数据库中,将返回一个对象 - 持久化的“this”以及db对其所做的任何更改,例如。时间戳。

Lhotka经常写得非常随意,你必须确保将对旧对象的所有引用更新为新返回的对象。有道理,但有没有一种简单的方法来查找旧对象的所有引用并更改它们? GC显然跟踪参考文献,是否可以利用它?

干杯

4 个答案:

答案 0 :(得分:5)

profiling API's这样做,但没有一般消费。一个可能的解决方案和我自己使用的解决方案是在基类中实现一个跟踪机制,其中对象的每个实例都将WeakReference添加到静态集合中。

我有条件地为DEBUG构建编译,但在发布版本中依赖它可能不是一个好主意。

// simplified example
// do not use. performance would suck
abstract class MyCommonBaseClass {

    static readonly List<WeakReference> instances = new List<WeakReference>();

    protected MyCommonBaseClass() {
        lock (instances) {
            RemoveDeadOnes();
            instances.Add(new WeakReference(this));
        }
    }

}

答案 1 :(得分:4)

GC实际上并不跟踪对象的引用。相反,它计算从运行时的全局和堆栈对象开始可以访问哪些对象,并执行“泛洪填充”算法的某些变体。

特别针对您的问题,为什么不让代理保持对“真实”对象的引用?这样您只需要在一个地方更新。

答案 2 :(得分:0)

没有一种简单的方法可以直接执行此操作,但是,罢工之子具有此功能。它允许您深入研究CLR跟踪的所有对象引用,并查看引用任何特定对象的对象等。

这是一个很好的tutorial for learning CLR debugging via SoS

答案 3 :(得分:0)

如果要传递对象引用并且这些对象引用保持不变,则对象的任何其他使用者都可以立即看到对持久层中对象所做的任何更改。但是,如果您的对象穿过服务边界,则对象每侧的程序集将查看仅为碳副本的不同对象。此外,如果您已经创建了对象的克隆,或者已经创建了包含原始对象的属性的匿名类型,那么这些将难以追踪 - 当然对于GC而言,这些是与之无关的新对象。原始对象。

如果对象中有某种键或ID,那么这将变得更容易。密钥不必是数据库ID,它可以是在实例化对象时新建的GUID,并且在对象的整个生命周期中不会被更改(即,它是具有getter但没有setter) - 因为它是一个属性,它将跨越服务边界,所以你的对象仍然是可识别的。然后,您可以使用LINQ或甚至老式循环(icky!)来遍历任何可能包含更新对象副本的集合,如果找到,则可以将更改合并回来。

说完这个,我不认为你有太多副本浮动。如果您这样做,那么这些副本的位置应该是非常本地化的。确保您的对象实现INotifyPropertyChanged还有助于传播更改通知,如果您在一个位置中保存一个列表,然后直接或间接绑定到其他几个位置。