2016-07-29 4 views
0

私はリクエストオブジェクトを発行するブローカクラスを持っており、カップルプロパティを合理的な値に変更してリクエストオブジェクトを返すことを期待しています。問題は、前記ブローカの消費者がでないことは、そのオブジェクトのreadonlyプロパティを変更したり、別のリクエストインスタンスを作成して読み取り専用保護を無効にしたり、ブローカが壊れて例外をスローすることができないことです。ブローカのクラス保存が要求オブジェクトを作成しようとすると、コンパイルに失敗する方法を見つけたいと思います。どうすればAクラスが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

プレイスPermissionsRequestBrokerと一緒に別のアセンブリでPermissionsRequest、及びinternal代わりにpublicとしてPermissionsRequestをマークします。次に、消費者が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

私は*別々のアセンブリに入れました;)あなたは正しいですが、ラッパーなしで行うことができますが、インプリメンテーションの詳細を隠すことが目的ならば、これを行う方法の1つです。さらに、 'PermissionsRequest'が" big "になり始めると、' internal' *と 'public'の両方の実装で煩雑になる必要はありません。 – Steve

1

なぜ、この作品ではないだろう...私はこれが既に回答されて知っているが、私は興味が?

EDIT:脳凍結の瞬間があった場合、以下のコードは機能しません。その後の編集を参照してください。

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

    public sealed class PermissionsRequest { 
     private PermissionsRequest() { 

     } 
    } 
} 

基本的に内部クラスを公開してシールしていますが、そのコンストラクタだけをプライベートにしますか?

EDIT

我々はこれを反転した場合、思考を実装する方が簡単でしょうか?もちろんブローカーの静的性はオプションです。

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

関連する問題