2009-02-06 80 views
6

這是我班的一個簡化版本:基類可以確定派生類是否已覆蓋虛擬成員?

public abstract class Task 
{ 
    private static object LockObject = new object(); 

    protected virtual void UpdateSharedData() { } 
    protected virtual void UpdateNonSharedData() { } 

    public void Method() 
    { 
     lock(LockObject) 
     { 
      UpdateSharedData(); 
     } 
     UpdateNonSharedData(); 
    } 
} 

我試圖隱藏從派生類的鎖定代碼。但是我只想獲取鎖定,如果派生類重寫UpdateSharedData;如果沒有,我不希望該方法阻止並等待更新共享數據之前更新共享數據的所有其他正在運行的實例。

所以Method(看似)顯而易見的事情是檢查當前實例的UpdateSharedData實現是否覆蓋了基類的實現。我敢肯定,如果不使用反射,這是不可能的,這可能不是可取的。

我想過一些解決方法,此的,但他們都非常尷尬:

  • 添加一個受保護的布爾屬性,派生類的構造函數集,並檢查屬性,看是否有鎖需要。這就隱藏了派生類中的鎖定代碼,這是非常糟糕的工作。
  • 使UpdateSharedData方法成爲委託屬性,讓任何派生類將其屬性設置爲其構造函數中的私有方法,並且只有在委託不爲null時才獲取鎖定。這更好,但它仍然很糟糕。

回答

4

如果你定義的抽象任務和IHasSharedData界面,然後在方法您檢查導出任務做之前實現IHasSharedData鎖。只有實現該接口的類需要等待。我意識到這可以避免回答實際問題,但我認爲這將是比使用反射更清晰的解決方案。希望你能找到一個更好的接口名稱,以更貼近實際的類。

public interface IHasSharedData 
{ 
    void UpdateSharedData(); 
} 

public abstract class Task 
{ 
    private static object LockObject = new object(); 

    protected virtual void UpdateNonSharedData() { } 

    public void Method() 
    { 
     if (this is IHasSharedData) 
     { 
      lock(LockObject) 
      { 
       UpdateSharedData(); 
      } 
     } 
     UpdateNonSharedData(); 
    } 
} 

public class SharedDataTask : Task, IHasSharedData 
{ 
    public void UpdateSharedData() 
    { 
     ... 
    } 
} 
4

爲此,您可以檢查與反思【熊:

bool IsUpdateSharedDataOverridden() 
{ 
    Type t = this.GetType(); 
    MethodInfo m = subType.GetMethod("UpdateSharedData"); 

    return m.DeclaringType == t && m.GetBaseDefinition().DeclaringType == typeof(Task); 
} 
+0

將m.DeclaringType直接與t進行比較會更加正確。兩種不同的類型很可能具有相同的名稱。 – JaredPar 2009-02-06 04:05:16

+0

如果使用「新」重新聲明(不覆蓋)該方法,那麼也會報告真實情況。 – 2009-02-06 04:15:34

0

其實,你在談論兩個不同的對象:

public abstract class Task {  
    protected virtual void UpdateNonSharedData() { } 

    public virtual void Method()  
    { 
     UpdateNonSharedData();  
    } 
} 

public abstract class TaskWithSharedData : Task {  
    private static object LockObject = new object();  

    protected virtual void UpdateSharedData() { } 

    public overrides void Method()  
    {  
     lock(LockObject) 
     {   
      UpdateSharedData();  
     } 
     base.Method(); 
    } 
} 

但更理想的解決方案將是策略模式。

相關問題