2009-12-05 56 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繼承的將得到相同的行爲。普雷斯托!