C# - 截获子类中的属性更改

本文关键字:属性 子类 | 更新日期: 2023-09-27 17:57:02

我正在创建一个框架,其中我提供了基类,框架的实现者将从基类继承并提供其他属性和方法。 在基类中,我想有一种观察属性值何时更改的方法。 该属性可以来自基类,也可以位于任何子类中。 我知道通过反射,我可以确定任何实例的属性列表,但是有没有办法跟踪属性更改值?

以下是我所说的一个非常简单的例子:

public class BaseClass
{
    public string BaseClassProperty { get; set; }
    public void DoSomethingWhenEitherPropertyGetsChanged()
    {
    }
}
public class SubClass : BaseClass
{
    public string SubClassProperty { get; set; }
}

当任何一个属性的值发生变化时,我该怎么做才能DoSomethingWhenEitherPropertyGetsChanged执行。

C# - 截获子类中的属性更改

您可以使用

notifypropertyweaver来实现此目的。 它完全符合您的要求。 这是一个链接:

  • 通知财产编织者

从开源主页:

使用 IL 编织(通过 http://www.mono-project.com/Cecil)将 INotifyPropertyChanged 代码注入到属性中。

  • 无需属性
  • 无需参考资料
  • 无需基类
  • 支持 .net 3.5、.net 4、Silverlight 3、Silverlight
  • 4、Silverlight 5 和 Windows Phone 7
  • 支持客户端配置文件模式

我可能会使用 Postsharp 并创建一个继承的属性,将拦截代码注入所有公共属性。将属性标记为继承也应自动将其附加到所有子类。

我写了我自己对您的要求的想法,但我不确定它是否适合您的需求。INotify属性更改是你也可以研究的东西,但我真的不喜欢它,因为它就像连接speghetti一样。不过,也许这会给你一些创造性的想法。

这样做的作用是允许您对所有属性类型使用 ObservableObject。通过执行此操作,每个属性都将有一个可以连接到的 ObjectChanged 事件。缺点是必须初始化构造函数中的所有属性,以防止代码中某处出现 NullReferenceException。

此示例使用三个类。

  • 可观察对象.cs
  • 员工.cs
  • 程序.cs

可观察对象.cs

    //-----------------------------------------------------------------------------
    // <copyright file="ObservableObject.cs" company="DCOM Productions">
    //     Copyright (c) DCOM Productions.  All rights reserved.
    // </copyright>
    //-----------------------------------------------------------------------------
    namespace PropertyChangedEventExample {
        using System;
        public class ObservableObject : Object {
            /// <summary>
            /// Expose the default constructor
            /// </summary>
            public ObservableObject() {
                // No default implementation
            }
            private object m_Object = null;
            /// <summary>
            /// Base object
            /// </summary>
            public object Object {
                get {
                    return m_Object;
                }
                set {
                    if (m_Object != value) {
                        m_Object = value;
                        OnObjectChanged(this, EventArgs.Empty);
                    }
                }
            }
            /// <summary>
            /// Triggered when the value of this object has changed.
            /// </summary>
            public event System.EventHandler<EventArgs> ObjectChanged;
            /// <summary>
            /// EventHandler wire-up
            /// </summary>
            protected virtual void OnObjectChanged(object sender, System.EventArgs e) {
                if (ObjectChanged != null) {
                    ObjectChanged(sender, e);
                }
            }
            /// <summary>
            /// Gets the value
            /// </summary>
            public object Get() {
                return this.Object;
            }
            /// <summary>
            /// Sets the value
            /// </summary>
            public void Set(object value) {
                this.Object = value;
            }
        }
    }

员工.cs

    //-----------------------------------------------------------------------------
    // <copyright file="Employee.cs" company="DCOM Productions">
    //     Copyright (c) DCOM Productions.  All rights reserved.
    // </copyright>
    //-----------------------------------------------------------------------------
    namespace PropertyChangedEventExample {
        using System;
        public class Employee {
            /// <summary>
            /// Expose default constructor
            /// </summary>
            public Employee() {
                Name = new ObservableObject();
            }
            /// <summary>
            /// Gets or sets the name
            /// </summary>
            public ObservableObject Name {
                get;
                set;
            }
        }
    }

程序.cs

    //-----------------------------------------------------------------------------
    // <copyright file="Program.cs" company="DCOM Productions">
    //     Copyright (c) DCOM Productions.  All rights reserved.
    // </copyright>
    //-----------------------------------------------------------------------------
    namespace PropertyChangedEventExample {
        using System;
        class Program {
            static void Main(string[] args) {
                Employee employee = new Employee();
                employee.Name.Set("David");
                employee.Name.ObjectChanged += new EventHandler<EventArgs>(Name_ObjectChanged);
                employee.Name.Set("Dave");
                Console.ReadKey(true);
            }
            static void Name_ObjectChanged(object sender, EventArgs e) {
                ObservableObject employee = sender as ObservableObject;
                Console.WriteLine("Name changed to {0}", employee.Get());
            }
        }
    }

最好的选择是CrisWue推荐的,并使用postsharp或其他一些后处理器将行为注入到您的属性中。除此之外,我认为您需要在您的属性中手动调用 DoSomethingWhenBothPropertyGetsChanged()。

如果要创建由您或您的组织以外的人员使用的库,则后处理器可能不是正确的方法,因为它将第三方工具作为另一个要求添加到其构建过程中。