0

私はIoCコンテナ(Unity)を使用しようとしており、それによって私のためにUDP通信を行うライブラリを作成しようとしています。メソッドコールのライフタイムとユニティとのパラメータ注入

基本的に、私は3つのクラス得た:

  • 以下インターフェース

    public interface IUdpClient 
    { 
        Task<UdpReceiveResult> ReceiveAsync(); 
        Task<int> SendAsync(byte[] datagram, int bytes); 
        Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint endPoint); 
        Task<int> SendAsync(byte[] datagram, int bytes, string hostname, int port); 
    } 
    
  • を実装するなど、いくつかの符号化/復号化を行うクラスコミュニケー、チェックサムチェックを実装するクラスUdpClientAdapterを次のインターフェース

    public interface ICommunicator 
    { 
        Task<int> SendAsync(int command, object dataObject = null); 
        Task<int> SendAsync(int command, IEnumerable<byte> data); 
        Task<T> ReceiveAsync<T>(); 
    } 
    
  • とコミュニケータの

    public interface IController 
    { 
        Task Start(); 
        Task Stop(); 
        Task<MachineStatus> ReadMachineStatus(); 
    } 
    

コンストラクタは

public Communicator(IUdpClient udpClient) 
{ 
    this.udpclient = udpClient; 
} 
ある下記(簡略化)インタフェースを実装する第三のクラスのコントローラ」だから、このクラスは、注入インスタンスIOC-コンテナ - UdpClientへの依存関係を作成します。 私の問題はコントローラクラスにあります。私は非同期メソッドを使用しているので、コントローラのメソッドを呼び出すたびに独自のCommunicator(したがってUdpClient)インスタンスが取得されるようにしたいと思います。私はちょうどcontainer.Resolve()を使用していますか?

私の2番目の質問は、Communicatorクラスのパラメータをどのように処理するかです。私の場合は、接続するUdpServer、つまりタイプIpEndPointのフィールドを設定する必要があります。私はちょうどそのフィールドのセッターでICommunicatorインターフェースを拡張するか、何とかコンストラクターに渡すべきですか?

おかげ

答えて

1

私は非同期メソッドで作業しておりますので、私は、コントローラのメソッドのすべての呼び出しは、これは大きな匂いである私には、独自のコミュニケー

を取得することを望みます。抽象化の消費者は、そのような抽象化のインスタンスが1つだけ存在する必要があります。あるいは、別の言い方をすれば、そのような抽象化には目立つステートフルさがあってはなりません。ステートフルな抽象化は消費者を複雑にします。また、実装の詳細がCommunicator実装から消費者への抽象化を通じて漏れていることを意味する可能性もあります。すべてICommunicatorの実装では、Controllerごとに1つの実装が必要ですか?

ここには複数の解決策があります。 Communicatorの実装を変更して、Controllerが単一のインスタンスで動作するようなステートレスになるようにするか、ステートフルな状態を防ぐことができない場合は、Communicatorを仮想プロキシの背後に隠してください。このようなバーチャルプロキシは、各メソッド呼び出しで新しいCommunicatorを作成できます。例えば:

public interface CommunicatorProxy : ICommunicator 
{ 
    private readonly Func<ICommunicator> factory; 
    public CommunicatorProxy(Func<ICommunicator> factory) { 
     this.factory = factory; 
    } 
    public Task<int> SendAsync(int c, object d) => factory().SendAsync(c, d); 
    public Task<int> SendAsync(int c, IEnumerable<byte> d) => factory().SendAsync(c, d); 
    public Task<T> ReceiveAsync<T>() => factory().ReceiveAsync<T>(); 
} 
+0

私のコミュニケーションはRequest-> Answerの仕方で動作するので、私はそれをステートレスに変更できないと思います。 1つのメッセージが送信される場合、私は答えを期待します。非同期(または別のスレッド)では、それを保証することはできません。したがって、各要求に対して独自のUdpClientが必要です。私は前もってコミュニケータのインスタンスを1つだけ実装しようとしましたが、私の要求に対して正しい答えを受け取ることが保証できないために失敗しました。少なくとも、何らかの共通バッファ/キューを使用しない限り、私は理解していません。 – kain

+0

あなたの提案したアプローチは私を助けません。 「コントローラ」の1つのメソッドのすべての送信/受信アクションが同じコミュニケータによって処理されることを保証する必要があります。 たとえば、 'ReadMachineStatus()'メソッドは、いくつかの送信操作と受信操作で構成されています。私は、対応するメソッドの回答のみを受け取るようにしなければなりません(そして、例えば、 'Stop'などの他のメソッド呼び出しではありません) – kain

関連する問題