2011-05-21 134 views
7

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

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

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

    public void DoSomethingWhenEitherPropertyGetsChanged() 
    { 

    } 
} 

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

我能做些什么有DoSomethingWhenEitherPropertyGetsChanged当任一属性都有它的价值变化得到执行。

+0

即使在基类中,你将不得不调用'DoSomethingWhenEitherPropertyGetsChanged()'在你的属性设置,所以你可以做同样的呼叫的制定者子类的属性。 – 2011-05-21 00:45:29

+0

对于任何有兴趣实现拦截器的人来说,看一看[TinyInterceptor](https://github.com/Jalalx/TinyInterceptor) – Jalal 2016-07-25 19:07:41

回答

4

您可以使用notifypropertyweaver来实现此目的。它确实是你想要的。这里有一个链接:

从开源主页:

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

  • 任何属性需要
  • 没有引用所需
  • 否基类需要
  • 支持.NET 3.5,.NET 4,Silverlight 3中,Silverlight 4中,的Silverlight 5和Windows Phone 7
  • 支架客户资料模式
+0

谢谢!经过快速测试,这似乎正是我所需要的! – 2011-05-21 01:44:24

+0

很高兴我能帮到你。这是一个非常酷的项目。 – 2011-05-21 01:50:06

+0

现在没有找到:( – kaspartus 2013-11-12 07:27:05

3

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

+0

你是说应该在'BaseClass'上创建一个属性来拦截setter方法在基类的所有属性以及任何继承类? – 2011-05-21 01:17:35

+0

Postsharp定义了一些基本上允许您将代码注入各种方法的属性。 – ChrisWue 2011-05-21 07:40:26

0

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

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

1

我写了我自己的想法,您的要求,但我不知道它是否适合您的需求。 INotifyProperty的改变是你可以研究的东西,但是我不太喜欢它,因为它就像接连接Speghetti。虽然这可能会给你一些创意。

这样做,可以让您使用ObservableObject作为您的所有属性类型。通过这样做,每个属性都会有一个可以连接到的ObjectChanged事件。 con(s)是你必须初始化构造函数中的所有属性,以防止代码中某处出现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()); 
      } 
     } 
    }