2009-12-05 78 views
5

C# - .net 3.5在访问类属性(get或set)时执行的方法?

我有一系列继承自同一基类的类。 我想要一个基类中的方法在任何时候访问一个衍生类的属性(get或set)时被调用。但是,我不想在每个属性中编写代码来调用基类...相反,我希望有一种声明方式将此活动“吸收”到基类中。

添加一些香料到需求,我确实需要确定被访问的属性的名称,属性值和它的类型。

我想象的解决方案将是一个委托,泛型和反射的巧妙组合。我可以设想在运行时创建一些类型的委托赋值,但是在构造函数中遍历MemberInfo会比我想要的影响性能。再次,我希望有一个更直接的“声明”方式来做到这一点。

任何想法都非常感谢!

回答

2

我不相信这是可以做出声明,我从来没有见过这样做。你可以做的是在你的基类上实现INotifyPropertyChanged接口,并且在基类中实现接口。就像这样:

public class A : INotifyPropertyChanged 
{ 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    protected virtual void RaiseOnPropertyChanged(object sender, string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      PropertyChanged(sender, new PropertyChangedEventArgs(propertyName); 
    } 

    public A() 
    { 
     this.PropertyChanged += new PropertyChangedEventHandler(A_PropertyChanged); 
    } 

    void A_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     //centralised code here that deals with the changed property 
    } 
} 


public class B : A 
{ 
    public string MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      _myProperty = value; 
      RaiseOnPropertyChanged(this, "MyProperty"); 
     } 
    } 

    public string _myProperty = null; 
} 
+0

我还应该指出,尽管INotifyPropertyChanged允许你传递一个属性名称,但它并不需要火箭科学家进一步理解这个概念,而是编写你自己的接口版本,它也允许属性值等通过。虽然你提出的建议虽然在理论上听起来很聪明,但会给你的应用增加很多开销,你将不得不考虑在你的代码中使用条件编译开关。 – slugster 2009-12-05 23:06:52

4

你不能自动做,但你几乎可以免费获得95%。这是面向方面编程的经典案例。检出PostSharp,其中有OnFieldAccessAspect类。以下是你可能如何解决你的问题:

[Serializable] 
public class FieldLogger : OnFieldAccessAspect { 
    public override void OnGetValue(FieldAccessEventArgs eventArgs) { 
     Console.WriteLine(eventArgs.InstanceTag); 
     Console.WriteLine("got value!"); 
     base.OnGetValue(eventArgs); 
    } 

    public override void OnSetValue(FieldAccessEventArgs eventArgs) { 
     int i = (int?)eventArgs.InstanceTag ?? 0; 
     eventArgs.InstanceTag = i + 1; 
     Console.WriteLine("value set!"); 
     base.OnSetValue(eventArgs); 
    } 

    public override InstanceTagRequest GetInstanceTagRequest() { 
     return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false); 
    } 
} 

现在,任何从FieldLogger继承的将得到相同的行为。普雷斯托!