2011-08-19 24 views
4

這可能是最簡單的代碼(這當然不是實際的代碼,但它具有相同的屬性)來解釋:重寫一個單一的接口方法時實現類是密封

我有一個看起來是一個接口像這樣:

public interface ISomeProvider 
    { 
     object GetFoo1(); //<-- This needs caching 

     //These others don't 
     object GetFoo2(); 
     object GetFoo3(); 

     //And let's say 20 more 
    } 

與此有類似這樣的實現:

//NOTE: Sealed class otherwise we could inherit from it 
    public sealed class SuperCleverProvider : ISomeProvider 
    { 
     public object GetFoo1() 
     { 
      return "a"; 
     } 

     public object GetFoo2() 
     { 
      return "b"; 
     } 

     public object GetFoo3() 
     { 
      return "b"; 
     } 
    } 

現在這些調用之一,讓我們說GetFoo1是真的很重,所以我想提供商一個接口的新版本,使用舊版本的一個實例緩存對它的調用。

我正在做這樣的時刻:

public class CachedSuperCleverProvider : ISomeProvider 
    { 
     private readonly SuperCleverProvider _provider; 

     public CachedSuperCleverProvider(SuperCleverProvider provider) 
     { 
      _provider = provider; 
     } 

     private object UsingCache<T>(string cacheKey, Func<T> eval) 
     { 
      //Pretend this does caching. This is not related to the question 
      throw new NotImplementedException(); 
     } 

     public object GetFoo1() 
     { 
      return UsingCache("foo1", _provider.GetFoo1); 
     } 

     //The code below this point is what I want to get rid of 
     public object GetFoo2() 
     { 
      return _provider.GetFoo2(); 
     } 

     public object GetFoo3() 
     { 
      return _provider.GetFoo3(); 
     } 

     //And so on for all the rest 
    } 

這有兩個問題(至少):

  • 每當有人向我必須去界面的方法改變這一點,即使我不想要這種新方法被緩存
  • 我得到這個龐大的無用的代碼列表,只是調用通過底層的實現。

任何人都可以想到一個這樣做的方式,沒有這些問題?

+0

你的方式是100%正確的 - 它是通過封裝繼承的。這是一個維護任務,但如果其中一個類已過期,則編譯器會通知您。 –

回答

3

三個選項:

  • 自動生成的類
  • 使用PostSharp或類似做更攔截器的方式
  • 與它生活

個人而言,我會的東西可能會與第三種選擇,除非你真的發現自己做了很多。權衡每個選項的成本 - 你多少時間實際上要花費增加這個代表團?

我個人倒喜歡看到這樣的事情作爲一個語言功能 - 「授人以這種接口,通過這個領域,除非我重寫它」,但顯然這是不存在的那一刻...

0

這是我的建議。這不是太好,但會簡化包裝過程。

創建一個類SomeProviderWrapper

public class SomeProviderWrapper : ISomeProvider 
{ 
    protected ISomeProvider WrappedProvider { get; private set; } 

    protected SomeProviderWrapper(ISomeProvider wrapped) 
    { 
     if (wrapped == null) 
      throw new ArgumentNullException("wrapped"); 

     WrappedProvider = wrapped; 
    } 

    public virtual object GetFoo1() 
    { 
     return WrappedProvider.GetFoo1(); 
    } 

    public virtual object GetFoo2() 
    { 
     return WrappedProvider.GetFoo2(); 
    } 

    public virtual object GetFoo3() 
    { 
     return WrappedProvider.GetFoo3(); 
    } 
} 

現在,包裹被轉移到自己的類,你可以寫緩存版本:

public class CachedSuperCleverProvider : SomeProviderWrapper 
{ 
    public CachedSuperCleverProvider(ISomeProvider wrapped) : base(wrapped) { } 

    private object UsingCache<T>(string cacheKey, Func<T> eval) 
    { 
     throw new NotImplementedException(); 
    } 

    public override object GetFoo1() 
    { 
     return UsingCache("foo1", WrappedProvider.GetFoo1); 
    } 
} 

這使代表團碼出你的超聰明的提供者。您仍然必須維護授權代碼,但它不會污染您的緩存提供者的設計。

相關問題