1

プロジェクトマネージャがアイドルアイドルを検索してアイドルを検索し、タスクを割り当てることができる、この(架空の)デスクトップアプリケーションがあります。モデルは次のとおりです。私はIDeveloper年代を取得する(入力された工場として設定されている)DeveloperFooFactoryを使用しますので、ウィンザー:ランタイム依存関係が含まれている場合のコンテナの設定方法

interface IDeveloperFactory 
{ 
    IDeveloper CreateDeveloper(string name); 
} 

interface IDeveloper 
{ 
    void WriteCode(); 
    void WriteUnitTest(); 
} 

interface ITask 
{ 
    void Complete(); 
} 

class Developer : IDeveloper 
{ 
    public Developer(string name) { ... } 

    public void WriteCode() 
    { 
     Console.WriteLine("Developer {0} is writing code... done", name); 
    } 
    public void WriteUnitTest() 
    { 
     Console.WriteLine("Developer {0} is writing unit test... done", name); 
    } 
} 

class WriteCodeTask : ITask 
{ 
    public Task(Lazy<IDeveloper> lazyDeveloper) { ... } 

    public void Complete() 
    { 
     var dev = lazyDeveloper.Value; 
     dev.WriteCode(); 
    } 
} 

Developerは、ランタイム依存関係を持っています。

var developerFactory = container.Resolve<IDeveloperFactory>(); 
var dev1 = developerFactory.CreateDeveloper("dev 1"); 
var task1 = container.Resolve<ITask>(); 
task1.Complete(); // uses dev1 
var task2 = container.Resolve<ITask>(); 
task2.Complete(); // uses dev1 
container.Release(dev1); // also releases task1 and task2 

var dev2 = developerFactory.CreateDeveloper("dev 2"); 
var task3 = container.Resolve<ITask>(); 
task3.Complete(); // uses dev2 
// task1, task2 and task3 are always different instances 

質問:

  1. IDeveloperが使用されている間、私はまた、それらを解決するために、私はちょうどコンテナを頼むことができればはるかに容易になり、開発者のインスタンスと私の作品を使用ITask年代を必要としますこれを実現するには、どのようにコンテナを設定できますか? (私はバージョン3.0を使用する予定です)
  2. dev2を作成する前にdev1をリリースしないのが理想的ですが(例えば、別のスレッドで同時にdevを作成してください)、まだ解決するコンテナが必要です。ITaskは適切です。このために子コンテナを使用する必要がありますか、3.0の新しいBeginScopeメソッドですか?
  3. 開発者が複数のタスクを異なるスレッドで同時に処理することも可能です。だから私はタスクが必要なときは、私はちょうどそれを解決し、 "コンテキスト開発者"のインスタンスを使用してコンテナを求めるだろう...しかし、どのように?

私は、それが循環依存性でない場合は、より簡単かもしれないことを認識しています。しかし、実際のモデルというのは、もっと自然な形になっているようです...

+0

'IFoo'と' IBar'の名前をアプリケーションで使用する実際の名前に変更すると、抽象的なものを抽象的なものにすることができます。このようにして、実際の設計について有用なことを言うことができます。 – Steven

+0

@スティーブン私は物事を少し抽象化しないように質問を編集しました。私は実際のモデルを共有することはできません、申し訳ありません。 HTH ... – Suiden

+0

'Developer'のようなものはエンティティです(IDeveloperFactoryは実際には' IDeveloperRepository'です)、コンテナにエンティティを作成して注入させようとしているかのように見えます。この質問を見てみましょう:http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-objec – Steven

答えて

0

最終的には...複雑に見えませんが、私はウィンザーにとって本当に新しいです。

コンテナ登録:

container.AddFacility<TypedFactoryFacility>(); 
container.Register(
    Component.For<IDeveloperFactory>().AsFactory(), 
    Component.For<IDeveloper>().ImplementedBy<Developer>().LifestyleScoped(), 
    Component.For<ITask>().ImplementedBy<WriteCodeTask>().LifestyleTransient(), 
    Component.For<Lazy<IDeveloper>>().LifestyleTransient() // i don't use 4.0 so this is my own implementation of Lazy<> which depends on a Func<> on ctor 
); 

テストコード:

var developerFactory = container.Resolve<IDeveloperFactory>(); 
using (container.BeginScope()) 
{ 
    var developer = developerFactory.Create("John"); // this creates a new Developer and caches it in the current scope 
    var task1 = container.Resolve<ITask>(); 
    var task2 = container.Resolve<ITask>(); 
    Assert.Same(task1.Developer, task2.Developer); 
    Assert.Equal("John", task1.Developer.Name); 

    task1.Complete(); 
    task2.Complete(); 
    container.Release(task1); 
    container.Release(task2); 
} 

これは、両方のタスクが同じ文脈現像インスタンスを使用して解決することができることを証明しています。

私の他の要求は、これが別のスレッドで動作することでした。 using (container.BeginScope()) { ... }コードをスレッド上で実行すると、コンテナはスレッドごとに異なる開発者インスタンスを作成してキャッシュするため、これも問題ありません。また、私はタスクを解決するために子スレッドを開始することができ、正しいコンテキスト開発者インスタンスを取得します。

関連する問題