我正在创建一个框架,在该框架中我提供基类,框架的实现者将从基类继承并提供其他属性和方法。在基类中,我希望有一种观察属性值何时更改的方法。该属性可以来自基类或任何子类。我知道通过反射,我可以从任何实例确定属性列表,但有没有办法可以跟踪属性更改值?
以下是我所说的非常简单的例子:
public class BaseClass
{
public string BaseClassProperty { get; set; }
public void DoSomethingWhenEitherPropertyGetsChanged()
{
}
}
public class SubClass : BaseClass
{
public string SubClassProperty { get; set; }
}
当任何一个属性的值发生变化时,如果DoSomethingWhenEitherPropertyGetsChanged
被执行,我该怎么做呢。
答案 0 :(得分:4)
您可以将notifypropertyweaver
用于此目的。它完全符合你的要求。这是一个链接:
从开源主页:
使用IL编织(通过http://www.mono-project.com/Cecil)将INotifyPropertyChanged代码注入属性。
答案 1 :(得分:3)
我可能会使用Postsharp并创建一个继承属性,将拦截代码注入所有公共属性。将属性标记为已继承也应自动将其附加到所有子类。
答案 2 :(得分:1)
我写了自己对你的要求的想法,但我不确定它是否适合你的需求。 INotifyProperty改变了你可以看到的东西,但我真的不喜欢它,因为它就像连接speghetti。也许这会给你一些创意。
这样做,允许您对所有属性类型使用ObservableObject。通过执行此操作,每个属性都将具有可以连接到的ObjectChanged事件。必须在构造函数中初始化所有属性,以防止代码中的某处出现NullReferenceException。
此示例使用三个类。
<强> 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()。
如果您正在创建一个由您或您的组织以外的人使用的库,则后处理器可能不是正确的方法,因为它将第三方工具添加为其构建过程的另一个要求。