2015-11-12 31 views
3

我試圖找到一個正確的方法來限制/強制使用方法,以確保正確的內部處理。C# - 強制重寫的方法被父級調用,而不是實例

給出下面的抽象基類

public abstract class BaseClass 
{ 
    // needs to be overriden by concrete implementation 
    protected abstract void CreateInternal(object dataToCreate); 

    // only visible method 
    public void Create(object dataToCreate) 
    { 
     // check the data provided <-- this is important to be done each time 
     CheckData(dataToCreate); 

     // call implementation of concrete class 
     CreateInternal(dataToCreate); 
    } 

    private void CheckData(object dataToCheck) 
    { 
     if(dataToCheck == null) throw new Exception("Data is not valid"); 
    } 
} 

和一個簡單的實現

public class ChildClass : BaseClass 
{ 
    protected override void CreateInternal(object dataToCreate) 
    { 
     // do create-stuff related to ChildClass 
    } 
} 

我的問題:有沒有辦法來限制訪問CreateInternal?在ChildClass我可以創建一個公共方法

public void DoStuff(object dataToDoStuff) 
{ 
    // access protected method is not forbidden 
    CreateInternal(dataToDoStuff); 
} 

這將調用CreateInternal沒有做必要的檢查,就好像如果通過基類的Create稱它爲會做。 有什麼辦法可以在CreateInternal之前強制使用Create?編譯時不需要(但它會很好),但至少在運行時。

我有類似的檢查誰打電話的想法。

public class ChildClass : BaseClass 
{ 
    protected override void CreateInternal(object dataToCreate) 
    { 
     // if not called via base 'Create' -> throw exception 
    } 
} 

有沒有某種模式我不知道或者是我想要實現的太過分了,根本不可能?

+0

您可以創建調用堆棧並檢查'Create'是否是最後一種方法(不包含當前方法),但這非常昂貴。問題是如果'Create'將會是虛擬的,並且有一個重寫的'Create'不會調用你的支票。不,我不認爲有強制調用方法的解決方案。唯一被保證的是ctor。首先調用Base Ctor。但是,嘿,這是保護。任何創建派生類並調用某些方法的人都應該知道他在做什麼。 –

回答

2

沒有辦法在編譯或運行時真正強制執行此操作。正如你所說的,一個virtual protected方法可以從任何派生類型訪問和覆蓋,所以你總是必須依靠overriden方法的實現來進行必要的檢查,這種方法會失敗。

恕我直言,你最好的辦法是通過代碼審查來強制執行,如果你能控制誰擴大你的班級。如果那不是那麼的話,看到你的Create方法不是虛擬的,而只是改變了BaseClass的狀態,爲什麼你不在構造函數中調用它?這是可能的還是你的例子是一個簡化的情況,這不是一個選項?這樣做可以保證始終首先調用Create

UPDATE:與我以前說過的相反,有一些「方法」可以在運行時強制執行。

雖然在你的例子中沒有顯示,但我猜測BaseClass中會有某種內部狀態,任何派生類都必須通過方法,屬性,字段等來使用它們(任何用途)(繼承是種類否則毫無意義)。如果沒有設置,您可以隨時在BaseClass中設置一個私有標誌createCalled,並使所有方法,獲得者(yuck)和設置者檢查標誌並用InvalidOperationException進行保護。這實際上會使沒有正確初始化的派生實例無用。醜陋但可行。

或者更簡單,如果你控制所有潛在消費者BaseClass和任何派生類型在野外擺在那裏,那麼就使標誌公共public bool Initialized { get; }和消費對象時檢查並在必要時救助。

0

「怪異」不會是我的選擇的話,但仍然..

據我所知,你試圖達到的目的是爲了防止實施CreateInternal()的方法體的ChildClass所有者首先不執行CheckData()而執行這些語句。

即使這樣做,他仍然可以將語句複製並粘貼到DoStuff()方法體中,並可以在其中執行它們。

我們不強迫,我們引導。

人們會遵循你的指導原則,他們會很高興看到他們的班級正在按照它的規定工作。

相關問題