2010-03-20 21 views
1

我有對象和集合,它應該支持Merge API(它是我的自定義API,其簽名對於這個問題來說是不重要的)。這個API必須是內部的,這意味着只有我的框架應該被允許調用它。但是,派生類型應該能夠覆蓋基本實現。如何在.NET中將公共API保留爲內部使用?

實施,因爲我認爲,這種模式自然的方式是這樣的:

  1. 的合併API被聲明爲一些internal接口的一部分,讓我們說IMergeable
  2. 由於界面是internal,派生類型將無法直接實現它。相反,他們必須從一個共同的基礎類型繼承它。因此,引入了一種通用的基本類型,它將顯式實現接口,其中接口方法委託給相應的受保護虛擬方法,提供默認實現。這樣API只能被我的框架調用,但派生類型可能會覆蓋默認實現。

下面的代碼段說明的概念:

internal interface IMergeable 
{ 
    void Merge(object obj); 
} 

public class BaseFrameworkObject : IMergeable 
{ 
    protected virtual void Merge(object obj) 
    { 
    // The default implementation. 
    } 

    void IMergeable.Merge(object obj) 
    { 
    Merge(obj); 
    } 
} 

public class SomeThirdPartyObject : BaseFrameworkObject 
{ 
    protected override void Merge(object obj) 
    { 
    // A derived type implementation. 
    } 
} 

所有是好的,提供一個單一的公共基類型就足夠了,這是通常用於非集合類型真。

事情是,集合也必須是可合併的。集合與所提出的概念並不搭配,因爲開發人員不會從頭開始開發集合。有預定義的實現 - 可觀察的,過濾的,複合的,只讀的,只能移除的,有序的,上帝知道的,......它們可以從頭開始在內部開發,但是一旦完成,它們就可以提供廣泛的產品不應該爲某些特定產品量身定製。這意味着,無論是:

  • 他們沒有實現IMergeable接口可言,因爲它是internal一些產品
  • IMergeable接口的範圍提高到public和API變得開放和可調用的所有。

讓我們將這些集合稱爲標準集合。無論如何,第一個選項是我的框架,因爲現在每個可能的標準集合類型都必須與相應的框架版本配對,用IMergeable接口實現來增強標準 - 這太糟糕了,我甚至沒有考慮它。

第二個選項打破了框架,因爲IMergeable接口應該是internal出於某種原因(不管它是什麼),現在這個接口必須向所有人開放。

那該怎麼辦?

我的解決方案是這樣的。使IMergeable公共API,但爲Merge方法添加一個額外的參數,我稱之爲安全令牌。接口實現可能會檢查該令牌是否引用了一些內部對象,這些內部對象從未暴露在外部。如果是這種情況,那麼該方法在框架內被調用,否則 - 一些外部的API消費者試圖調用它,所以實現可能會爆炸一個SecurityException

這裏是修改後的代碼片段演示這一概念:

internal static class InternalApi 
{ 
    internal static readonly object Token = new object(); 
} 

public interface IMergeable 
{ 
    void Merge(object obj, object token); 
} 

public class BaseFrameworkObject : IMergeable 
{ 
    protected virtual void Merge(object obj) 
    { 
    // The default implementation. 
    } 

    public void Merge(object obj, object token) 
    { 
    if (!object.ReferenceEquals(token, InternalApi.Token)) 
    { 
     throw new SecurityException("bla bla bla"); 
    } 

    Merge(obj); 
    } 
} 

public class SomeThirdPartyObject : BaseFrameworkObject 
{ 
    protected override void Merge(object obj) 
    { 
    // A derived type implementation. 
    } 
} 

當然,這比具有內部範圍接口更少顯式校驗被從編譯時移動到運行時間,然而,這是最好的我可以拿出來。

現在,我有一種直覺,認爲有更好的方法來解決我提出的問題。 我不知道,可能會使用一些標準的Code Access Security功能?我對它只有模糊的理解,但LinkDemand屬性可能與它有某種相關性?無論如何,我想聽聽其他意見。

回答

0

根本不要嘗試修改對象。改爲創建合併服務。

public interface IMergerService 
{ 
    void Merge(object value); 
} 

,並建立併購每種類型你支持:

public interface IMergerFor<T> where T : class 
{ 
} 

public class UserMerger : IMergerFor<User> 
{ 
} 

通過這種方式,你可以暴露用戶可以使用,並保留所有的祕密細節隱藏在定製的API。

+0

IMergertService.Merge的實現將如何工作? UserMerger是否具有用戶內部知識?有什麼好處,除了打破用戶封裝? – mark 2011-05-08 09:26:32

+0

我不是心靈的。你沒有描述合併過程如何工作。任何擁有原始對象中的合併對象的人都會破壞SRP。 – jgauffin 2011-05-09 04:51:36

相關問題