かなり長い間これに苦労してきたので、アンチパターンを作成したと思い始めています。それにもかかわらず、ここに行きます。
//Register self
container.Register(Component.For<IWindsorContainer>().Instance(container));
//Register all
container.Register(Component.For<IService1>().ImplementedBy<Service1>());
container.Register(Component.For<IService2>().ImplementedBy<Service2>());
//etc
IService1
{
//blabla
}
IService2 {IService1 Service1{get;}}
したがって、IService1 と IService2 は特別なことをしなくても作成できます。IService3 から、IProject が関与します。
IProject{}
//Resolve a service that, amongst other things, relies on an IProject
IProjectGet
{
T Get<T>(IProject proj)
where T : class;
}
//Impl
ProjectGet : IProjectGet
{
IWindsorContainer _cont;
public ProjectGet(IWindsorContainer cont){_cont=cont}
public T Get<T>(IProject proj)
{
//Resolve using the main (and only) container and pass the IProject
return _cont.Resolve<T>(new {p = proj});
}
}
これは機能しません。メイン サービスのみが 'p = proj' で解決され、メイン サービスが持つその他の依存関係 (プロジェクトに依存するもの) によって、プロジェクト サービスが見つからないという例外が発生します。
IService3
{
IService2 Service2{get;}
IProjectGet ProjectGet{get;}
IProjectLevelStuff SetActiveProject(IProject proj);
}
Service3 : IService3
{
IService2 Service2{get;private set;}
IProjectGet ProjectGet{get;private set;}
public Service3(IService2 s2, IProjectGet p)
{
ProjectGet = p;
Service2 = s2;
}
public IProjectLevelStuff SetActiveProject(IProject proj)
{
return ProjectGet.Get<IProjectLevelStuff>(proj);
}
}
ProjectLevelStuff : IProjectLevelStuff
{
IProject Project{get;private set;}
IService4 Service4 {get;private set;}
public ProjectLevelStuff(IProject p, IService4)//etc.
}
IService4
{
IService2 Service2{get;}
IService5 Service5{get;}
IService6 Service6{get;}
IProject Project{get;}
}
IService5{IProject Project{get;}}
IService6{IProject Project{get;}}
ProjectLevelStuff だけが渡された IProject を取得し、IService4 とその依存関係もそれを必要とするため、例外がスローされるため、これは失敗します。これが機能したとしても、IProject に依存する各サービスは、回避したいパラメーター「p」を強制的に呼び出すため、好きではありません。
既に持っているサービスを使い続けたいだけですが、今回は、解決可能な依存関係として汎用の Get メソッドに渡された IProject インスタンスを追加します。コンテナーをコピーして新しいコンテナーを作成し、メインのコンテナーを子として追加しても何も変更されません (依存関係がまだ失われています)。これはどのように行われますか?
Castle Windsor には TypeFactory が組み込まれていますが、基本的には私が既に行っていることと同じことを行い、何も解決しません。私が見つけた唯一の「解決策」は、新しいコンテナを作成してタイプをもう一度登録することですが、今回はメインコンテナを介してそれらを解決します(もちろんIProjectを除く)..これはメンテナンスの悪夢です。
更新: 以下の回答にいくつかの単体テストを追加しました。