【问题标题】:Base Class Awareness of Property Changes in Derived Classes派生类中属性变化的基类感知
【发布时间】:2009-12-21 23:36:23
【问题描述】:

我想知道是否有人对以下问题有可能的解决方案...我有一个基类,一系列派生类将从该基类继承。基类关心派生类的属性是否发生了变化。这是为数据传输对象设置“IsDirty”方法。

传统方法是设置在基类中声明的 IsDirty 布尔标志。我希望以某种方式避免这种情况,并想知道是否有另一种方法?我担心开发人员不记得在派生类中的属性的等效设置操作中设置标志。我曾考虑过创建一个通用的“SetProperty”方法来获取属性名称和值,但认为可能会有更优雅的东西。

顺便说一句,关于使用反射的想法不是问题。不管反思的代价是什么,我想证明一种方法来做到这一点,并努力在未来进一步完善它。

【问题讨论】:

    标签: c# oop inheritance data-structures


    【解决方案1】:

    你能强制派生类实现 INotifyPropertyChanged 吗?在这种情况下,我会在基类构造器中为 PropertyChanged 事件添加一个侦听器,然后进行冷静。派生类现在仍然需要遵循模式(这可能是您想要避免的事情?)。

    很好地阅读了用于引发属性更改事件的“不使用文字字符串”方法:http://monotorrent.blogspot.com/2009/12/yet-another-inotifypropertychanged-with_06.html

    【讨论】:

    • 哇。多么优雅的解决问题的方法!我查看了 INotifyPropertyChanged 接口,但我能找到的大多数示例仍然取决于每个设置器都有额外的代码。
    • 至于必须在派生类中完成工作,我不介意。我做好了充分的准备,不会有一个完整的“灵丹妙药”解决方案,但到目前为止,这样做的利大于弊。我会试一试,并可能将其标记为答案。
    • 效果很好!非常感谢。
    【解决方案2】:

    用于控制对一个类(或一组类)的访问的适当模式是代理模式。这种模式将允许您在代理级别实现一次正确的 isDirty 行为,并将任何只读行为委托给未更改的真实实例。

    当与工厂模式一起使用来控制实例的创建时,此模式最有效。

    此解决方案将掩盖实例的运行时类型,因此如果您的设计依赖于运行时类型信息,您将需要单独解决此问题(例如使用状态模式)或寻找替代方法。

    【讨论】:

    • 绝对是一种有趣的方法,但我确实需要运行时类型信息(即使用这些对象的“发现服务”)。我不知道为什么我没有考虑状态模式,因为事后看来这似乎很明显。 :-)
    【解决方案3】:

    (又快又脏)- 这样的事情怎么样? (您对 GetHashCode 的实现可能会有所不同 - 我使用 ReSharper 自动生成这个)

        public abstract class Animal
        {
            private int _originalHash;
    
            public string Name { get; set; }
            public int Age { get; set; }
    
            public Animal(string name, int age)
            {
                this.Name = name;
                this.Age = age;
    
                this._originalHash = GetHashCode();
            }
    
    
            public override sealed int GetHashCode()
            {
                unchecked
                {
                    return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ Age;
                }
            }
    
            public bool IsDirty
            {
                get
                {
                    return this._originalHash != GetHashCode();
                }
            }
        }
    
        public class Cat : Animal
        {
            public Cat(string name, int age)
                : base(name, age)
            {
            }
        }
    

    用这个来测试...

    var cat = new Cat("BobTheCat", 12);
    Console.WriteLine(cat.IsDirty);
    cat.Age = 13;
    Console.WriteLine(cat.IsDirty);
    

    结果是:

    错误 是的

    【讨论】:

    • 不错的方法,我可以看到它会如何运作。我对这种方法的唯一问题是它是一种“全有或全无”的方法。我没有在原始问题中具体说明,但很可能无法跟踪某些属性的更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 2016-04-29
    • 2017-07-05
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多