2016-07-29 100 views
0

我有一個代理類發出請求對象,並期望它們被傳回給它,並將一些屬性更改爲明智的值。問題是,的消費者表示,券商必須從未更改該對象的一對夫婦的只讀屬性,也可以創建不同的請求實例作弊是隻讀保護或經紀人將打破,並拋出一個異常。如果代理的任何類保存嘗試創建請求對象,我想找到一種方法來使編譯失敗。如何確保只有一個類可以創建一個A.B實例?

我認爲密封請求對象的實例化,所以它只能從代理內部完成本身是一個整潔的想法,加上只讀屬性,所以請求處理器永遠不會欺騙系統,但我很難做到這一點。我試過一個像這樣的私人構造函數的子類:

public class PermissionsRequestBroker { 
    public PermissionsRequest Test() { 
     return new PermissionsRequest(); 
    } 

    private class PermissionsRequest { 
     private PermissionsRequest() { 

     } 
    } 
} 

但它失敗了,因爲代理無法創建請求對象。

我嘗試過類似的方法,但用的接口是這樣的:

public class PermissionsRequestBroker { 
    public IPermissionsRequest Test() { 
     return new PermissionsRequest(); 
    } 

    public interface IPermissionsRequest { 

    } 

    private class PermissionsRequest : IPermissionsRequest { 
     public PermissionsRequest() { 

     } 
    } 
} 

但請求處理器可以實現IPermissionsRequest和欺騙系統的方式。當然,我可以實現一個運行時檢查,以便返回的對象仍然是代理的PermissionRequest對象,但這仍然是一個運行時檢查,並會引發異常。

我所有的異常,但我覺得必須有某種方式來強制執行該合同在編譯時,無需安裝任何形式的IDE擴展或NuGet包。

+0

什麼問題是你想解決? 「欺騙」是什麼意思,你不相信你的圖書館的用戶?你看過'sealed'關鍵字嗎? – Aron

+0

爲什麼你在第一個案例中使構造函數保密?在班級本身是私人的時候不會公開,而不是公開解決你的問題? – Madhusudhan

+0

@Aron PermissionRequest實例具有絕對不能更改的RequestId屬性。IE:如果經紀人向您發送一個帶有Id:0的請求,那麼經紀人會希望您使用同一個ID回覆,否則經紀人本身會中斷並回復不同的請求源。 – Machinarius

回答

1

地點PermissionsRequestBrokerPermissionsRequest在一個單獨的組件固定在一起,並標記爲PermissionsRequest代替internalpublic。然後,如果您需要消費者能夠堅持PermissionsRequest對象的實例,請將其包裝在另一個類爲public的類中。

類似以下內容:

public class PermissionsRequestBroker { 
    public PermissionsRequestWrapper Test() { 
     return new PermissionsRequestWrapper(new PermissionsRequest()); 
    } 
} 

internal class PermissionsRequest { 
    internal PermissionsRequest() { 

    } 
} 

// Use 'sealed' to prevent others from inheriting from this class 
public sealed class PermissionsRequestWrapper { 
    private PermissionsRequest _permissionsRequest; 

    internal PermissionsRequestWrapper(PermissionsRequest permissionsRequest) { 
     _permissionsRequest = permissionsRequest; 
    } 

    /* etc... */ 
} 
+0

哇。從來沒有想過這樣一個聰明的解決方案。 – Machinarius

+0

如果請求(或包裝器)的使用者在同一個程序集中,那麼他們仍然可以創建一個包裝器的實例。如果消費者在另一個程序集中被冒用,那麼可以簡單地使請求的構造函數成爲內部的。 – Maarten

+0

I * did * day將它們放入單獨的程序集中;)您說得對,您可以不使用包裝程序,但如果意圖隱藏某些實現細節,則可以這樣做。另外,如果'PermissionsRequest'開始變得「​​大」,它不必與'internal' *和*'public'實現混雜在一起。 – Steve

1

我知道這已經回答了,但我很好奇......爲什麼不這項工作?

編輯:有一個腦凍結的時刻,下面的代碼將無法正常工作,請參閱後編輯。

public class PermissionsRequestBroker { 
    public PermissionsRequest Test() { 
     return new PermissionsRequest(); 
    } 

    public sealed class PermissionsRequest { 
     private PermissionsRequest() { 

     } 
    } 
} 

基本上使得內部類公共和密封的,但只有它的構造函數私有?

編輯

如果我們反轉這一點,這將是容易實現,想法嗎?經紀人的靜態當然是可選的。

public class PermissionsRequest 
{ 
    private PermissionsRequest() 
    { } 

    public sealed class Broker 
    { 
     public static PermissionsRequest CreatePermissionsRequest() 
     { 
      return new PermissionsRequest(); 
     } 

     public PermissionsRequest CreatePermissionsRequest_Instance() 
     { 
      return new PermissionsRequest(); 
     } 
    } 
} 

public class UserClass 
{ 
    public void Blah() 
    { 
     var permissionsRequest = PermissionsRequest.Broker.CreatePermissionsRequest(); 

     var broker = new PermissionsRequest.Broker(); 

     var permRequest = broker.CreatePermissionsRequest_Instance(); 
    } 
} 
+0

構造函數是私有的,所以不是事件PermissionsRequestBroker可以調用它 – Machinarius

+0

哦,我的壞,我的大腦工作的對立方式,子類可以訪問父類的私人東西。 –

+0

沒問題。每個人都有這些時刻。 – Machinarius

相關問題