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

时间:2011-05-21 00:41:35

标签: c# .net c#-4.0 .net-4.0

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

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

public class BaseClass
{
    public string BaseClassProperty { get; set; }

    public void DoSomethingWhenEitherPropertyGetsChanged()
    {

    }
}

public class SubClass : BaseClass
{
    public string SubClassProperty { get; set; }
}

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

4 个答案:

答案 0 :(得分:4)

您可以将notifypropertyweaver用于此目的。它完全符合你的要求。这是一个链接:

从开源主页:

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

  • 无需属性
  • 无需参考
  • 不需要基类
  • 支持.net 3.5,.net 4,Silverlight 3,Silverlight 4,Silverlight 5和Windows Phone 7
  • 支持客户端个人资料模式

答案 1 :(得分:3)

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

答案 2 :(得分:1)

我写了自己对你的要求的想法,但我不确定它是否适合你的需求。 INotifyProperty改变了你可以看到的东西,但我真的不喜欢它,因为它就像连接speghetti。也许这会给你一些创意。

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

此示例使用三个类。

  • ObservableObject.cs
  • Employee.cs
  • Program.cs的

<强> ObservableObject.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;
            }
        }
    }

<强> Employee.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;
            }
        }
    }

<强> Program.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());
            }
        }
    }

答案 3 :(得分:0)

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

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