2010-07-07 67 views
7

我定義爲IStore的接口,有兩個方法:C# - 接口/抽象類 - 確保事件引發的方法

public interface IStore<TEntity> 
{ 
    TEntity Get(object identifier); 
    void Put(TEntity entity); 
} 

我想成爲把 的成功引發的事件(參考,放可以存儲一個行中的DB或文件系統等文件上...)

因此,實施Istore類型產品的一類看起來有點像這樣:

class MyStore : IStore<Product> 
{ 
    public Product Get(object identifier) 
    { 
     //whatever 
    } 

    public void Put(Product entity) 
    { 
     //Store the product in db 
     //RAISE EVENT ON SUCCESS 
    } 
} 

我所追求的是確保IStore的每個實現都引發該事件的方法 - 應該改爲抽象類,還是接口?

回答

9

我的建議:

public abstract class Store<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 
    public void Put(TEntity entity) 
    { 
     //Do actions before call 
     InternalPut(entity); 
     //Raise event or other postprocessing 
    } 

    protected abstract void InternalPut(TEntity entity); 
} 

然後覆蓋InternalPut在類

+1

這是我的答案。在某種程度上,當你允許方法被覆蓋時,你總是依賴於理解合同的人。但是提供這樣的框架可以讓你對事物允許發生的順序有一些控制。 – unholysampler 2010-07-07 12:30:30

1

是的,你應該使用抽象類而不是接口。

如果您決定使用實現您的接口的抽象類,它不會阻止其他開發人員實現他們自己的接口版本,最終不會引發事件。即使使用抽象類,也不會強迫其他開發人員使用您的方法,因爲他們可能會覆蓋它。

我認爲最好的方法是使用一個模板方法:

public abstract class AbstractStore<TEntity> 
{ 
    public TEntity Get(object identifier); 
    public sealed void Put(TEntity entity) 
    { 
     if (DoPut(entity)) 
     { 
      // raise event 
     } 
    } 

    protected abstract bool DoPut(TEntity entity); 
} 

真正的商店將必須實現DoPut方法,返回boolean值,指示認沽操作成功。該事件將從Put方法中提出,Put方法是公開可見的。

+0

它不會停止繼承類重寫行爲。沒有真正的方法來保證這種行爲。 – 2010-07-07 12:26:27

3

確實沒有辦法確保IStore的每個實現都引發一個事件。您可以擁有一個具有put方法的抽象類,但這並不意味着您可以在完全忽略抽象類方法的抽象類的子類中使用put方法。

最後,鼓勵的最好方法是通過抽象類來編寫開發人員應該使用的方法。這樣一來,他們必須走出自己的路使用它

2

你需要有抽象類實現put方法從你的界面。你還可以添加像PutImpl抽象方法,像這樣:

public abstract class MyStoreBase : IStore<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 

    public abstract void PutImpl(TEntity entity); 

    public void Put(TEntity entity) 
    { 
     // Each inheritor will implement this method. 
     PutImpl(entity); 

     // But event is fired in base class. 
     FireEvent(); 
    } 
} 
0

如果你確實需要使用一個接口,那麼新PostSharp 2能做方面繼承。不幸的是,要獲得該功能,您需要至少購買200美元的個人許可證。

有了這樣的一個方面,你可以把它放在你的接口聲明的方法上,接口的所有實現都會繼承它。

0
abstract class Store<TEntity> 
{ 
    public abstract TEntity Get(object identifier); 
    protected abstract void Put(TEntity entity); 
    public void PutBase(TEntity entity) 
    { 
     Put(entity); 
     //Raise event here 
    } 

} 

一些注意事項:我做了保護,所以派生類必須實現它,但客戶端代碼無法調用它。

0

寫一個抽象類來包裝類似PutInner的方法絕對是解決這個問題的最好方式,正如其他人已經提出的那樣。

我只想補充一點,如果你想爲IStore<TEntity>總是引發事件的任何執行時Put叫,我也建議增加表示事件接口本身:

public interface IStore<TEntity> 
{ 
    event EventHandler<EntityEventArgs<TEntity>> EntityAdded; 

    TEntity Get(object identifier); 
    void Put(TEntity entity); 
} 

public EntityEventArgs<TEntity> : EventArgs 
{ 
    public TEntity Entity { get; set; } 
} 

這並未't 強迫執行者做任何事情;但它確實明確地建立了EntityAdded將在成功的Put上籌集的期望。