2012-11-17 16 views
12

シングルプレイヤーからマルチプレイヤーにゲームをアップデートしています。この場合、ゲームはもともとほとんどのクラスが単一インスタンス化されて書かれていました。例えば1つのPlayerオブジェクト、1つのGameStateオブジェクトなどがありました。つまり、これらのオブジェクトのそれぞれは、アプリケーションと同じくらい長く存続しました。オブジェクトライフサイクル管理とIoCコンテナ

複数のプレイヤーが同時にプレイできるようになったので、複数のPlayerオブジェクト、GameStateオブジェクトなどの作成をサポートする必要があります。この作業を進めるうちに、ほとんどのオブジェクトには3つのlifespans:

  1. アプリの寿命ナビゲーションを処理する指揮者
  2. プレーヤーの寿命現在のプレーヤーのためのSettingsViewModel
  3. ゲームの寿命、現在のゲームのGameState

IoCコンテナを使用してこれらのさまざまなオブジェクトの作成を扱う人はどうですか?私は、プレーヤーまたはゲームの寿命で各クラスのファクトリクラスを作成しないようにしたいと思います。

+0

ライフスタイル/ライフタイムの設定は、通常、ほとんどのDIコンテナでサポートされています。どのプラットフォームとDIフレームワークについて話していますか? – Steven

+0

いくつかのコンテナは、ある程度のライフタイム管理をサポートしていますが、IPlayerをパラメータとするクラスを想像してください(この場合、多くのクラスがそうします)。単一のコンテナがある場合、ランタイムデータのファクトリを必要とせずにこのクラスをどのように登録しますか?私は、ライフサイクルごとに別々のコンテナを作成することを実験しましたが、複数のライフスパンに関わる懸念がある場合には、さまざまな部分を結びつけるためにまだ苦労しています。 –

+0

この場合は.NET/C#ですが、私は実際にこの設計問題をより一般的に解決する方法に興味があります。特に、私が対象としているすべてのプラットフォームでは利用できない可能性があるため、特定のコンテナにあまり依存したくありません。参考文献: –

答えて

0

Hereは、役に立つかもしれないIOCの例です。このプロジェクトは、IOC-with-Ninjectと呼ばれています。 NinjectとIOCコンテナクラスを使用して、すべてのオブジェクトの寿命を管理します。特定のニーズに合わせて少しカスタマイズするには少しresearch on Ninjectする必要がありますが、.NETを使用している場合はIOCコンテナソリューション(IMHO)であり、コードベースを整理するのに役立ちます。これは個人的な選択ですが、私はそれで誓います。 .NETを使用していない場合、それはあなたに続く簡単なパターンを与えます。乾杯。

0

多くのIoCコンテナには、あなたが望むように管理できるカスタムライフサイクルスコープがあります。

kernel.Bind<IService>().To<Service>().InScope((c, o) => yourCustomeScope); 

を限りyourCustomeScope変数が変更されていないとして、サービスオブジェクトの1つのインスタンスが毎回返されたカーネルはIServiceの要求を受信します。たとえば、次のようにNinjectでは、あなたのカスタムライフサイクルの範囲を定義することができます。 yourCustomeScope変数が変更されるとすぐに、次のIService要求時にServiceの新しいインスタンスが作成されます。 yourCustomeScopeは、現在のプレーヤーインスタンス、ゲームオブジェクト、または参照の変更に基づいてServiceオブジェクトの有効期間を変更するものにすることができます。

しかし、あなたが言及したオブジェクトは、注入が良い考えではないと思うサービスではなく、エンティティである可能性が高くなります。

0

私の経験から、工場のアプローチが最も効果的です。

サポートのためにインスタンスの寿命を制御することは頑丈であり、すべてのクラスの寿命要件と依存性、構成の構成と管理の時間を熟知している必要があります。同時に、工場の使用は自然でコード固有です。

proxy factoriesを使用すると、ファクトリ(実装)の作成を回避できます。ファクトリ(インターフェイス)の作成の必要性をさらに減らすために、ファクトリに汎用引数を返すようにすることもできます。

あまりにも多くの工場が必要な場合は、コードフローを確認することをお勧めします。

0

これは部分的には前回の回答のコメントの一部であると思いますが、私は推論のいくつかを少し例証しようとしました。

注入されたオブジェクトの寿命を管理する領域に入ると、おそらくこれらのオブジェクトのファクトリを作成する必要があります。

基本的な問題は、コンポジションルートが、オブジェクトを作成するために必要なコールの環境コンテキストを認識していないことです。

私は一歩踏み出してこの時点で説明する必要があると思います。

依存性注入に関する知恵は、コードのエントリポイントの近くにいくつかの構成ルートを持つことです。これにはウェブで見つけるのが難しくない多くの理由がありますので、ここでは取り上げません。

コンポジションルートは、インターフェイス(通常はオブジェクトですが)をインプリメントにマップする場所です。この時点で利用可能な情報をコンストラクタに渡すことができます。したがって、コンポジションルートの実行時にライフタイムが現在のオブジェクトへの参照を渡すことができます。

ただし、作成するオブジェクトのライフタイムとコンポジションルートのライフタイムが重ならない場合は、オブジェクトを作成する必要があるまでコンストラクタの実行を延期する必要があります。これが工場を持つ必要がある理由です。この時点で、ファクトリメソッドをマッピングに渡して、オブジェクトを生成するのに必要な情報を渡すことができますが、コンポジションルートが実行されていないときに作成が行われるようにすることができます。

ファクトリクラスは必要ありません。このファクトリメソッドはうまくいきますし、さらにファクトリメソッドをインライン化することもできます。したがって、コードオーバーヘッドは合成ルートにオブジェクトを作成する場合に比べてあまり重要ではありません。

最初のサービスが最初のサービスに依存する2つのサービスを持つプロジェクトがあり、最初のサービスを作成するときに2番目のサービスのライフタイムを開始したい場合は、次のようなものがあります。 (私は、コード例を与えることをninject使用していますが、私は他のIOCのコンテナが、この点でも同様に動作することを期待しています。)

 

` 
    public class Service1:IService 
    { 
     private Func<IService>serviceFactoryMethod _Service2Factory; 
     public Service1(Func<IService>service2FactoryMethod) 
     { 
      _Service2Factory=service2FactoryMethod; 
     } 

     public void DoSomethingUsingService2() 
     { 
      var service2=_Service2Factory(); 
      service2.DoSomething(); 
     } 
    } 

    public class MainClass 
    { 
     public void CompositionRoot() 
     { 
      var kernel= new StandardKernel(); 
      kernel.Bind.ToMethod(m=> 
      { 
       return new Service1(m.Kernel.Get<IService2>()); 
      } 
     } 
    } 

` 

この例を使用すると、アプリケーションの寿命を管理する方法を扱っていません。 、プレイヤー、ゲームのライフスパンなどが含まれていますが、従属注入に関連する生涯の問題を取り除く方法についての十分な手がかりを与えられれば幸いです。

サイドノート:Ninjectを使用すると、Service2の有効期間を管理してService1の有効期間を過ごすことができるようになります。たとえば、ゲームの各インスタンスが独自のスレッドで実行されていることが分かっている場合(OK、これは多分そうではないかもしれません)、InThreadScopeをゲームに使用する可能性があります。

関連する問題