Castle Windsorを使用して登録せずにクラスを解決する
-
22-07-2019 - |
質問
次の役に立たないプログラムを使用してください:
class Program
{
static void Main(string[] args)
{
IUnityContainer unityContainer = new UnityContainer();
IWindsorContainer windsorContainer = new WindsorContainer();
Program unityProgram = unityContainer.Resolve<Program>();
Program castleProgram = windsorContainer.Resolve<Program>();
}
}
UnityContainerはProgramのインスタンスを返します。WindsorコンテナーはComponentNotFoundExceptionをスローします。
両方の動作の引数を見ることができますが、どちらになってしまうかは気にしませんが、Prism V2 Drop 8(執筆時点では最新)は内部的にUnity動作に依存しており、登録されていないクラスを要求します。
これらのクラスをすべてPrismで見つけて登録するのではなく、WindsorをUnityのように動作させたいです。 Googleでこれを行うのに役立つものは何も見つかりませんでした(ただし、用語は間違っている可能性があります)。Windsorのドキュメントは非常に悪いです...
誰でもこの問題の解決策を提案できますか?
解決
現在、Windsorはこれをサポートしていません。これは仕様によるものです。その理由は、誤って設定されたオブジェクトを取得しないように、必要なタイプを明示的に登録する必要があるからです。
ただし、WCF統合機能で必要とされるため、近い将来のある時点で非登録型を作成するフックが追加される可能性があります。 (編集-v2.1で追加されました- ILazyComponentLoader
sをご覧ください)
とにかく、遅延コンポーネントローダーに関係なく、できることはFluent APIを使用して、事前に必要な条件に一致するアセンブリからすべてのタイプをバッチ登録することです。コードはそれほど多くないので、夜はよく眠れます。
必要なコンポーネントを判断するために、起動時に( composition root に)十分な情報がない場合にのみ、レイジーローダーを使用します。
他のヒント
Windsorはそのままではサポートしていませんが、拡張メソッドを作成してこれを行うことができます。
static class WindsorExtensions
{
public static object ResolveType(this IWindsorContainer container, Type type)
{
if ( type.IsClass && !container.Kernel.HasComponent(type) )
container.Kernel.AddComponent(type.FullName, type, LifestyleType.Transient);
return container.Resolve(type);
}
public static T ResolveType<T>(this IWindsorContainer container)
{ return (T)ResolveType(container, typeof(T)); }
}
class Program
{
static void Main(string[] args)
{
IUnityContainer unityContainer = new UnityContainer();
IWindsorContainer windsorContainer = new WindsorContainer();
Program unityProgram = unityContainer.Resolve<Program>();
Program castleProgram = windsorContainer.ResolveType<Program>();
}
}
Krzysztofは、ここで自分のブログにリンクすることを恐れないでください:) http://devlicious.com/blogs/krzysztof_kozmic/archive/2009/11/16/castle-windsor-lazy-loading.aspx
また、この単純な実装が私のWPFアプリで有用であることがわかりました。文字列の制約を削除すれば、一般的なケースに近いことになります
public class ViewModelLoader : Castle.MicroKernel.Resolvers.ILazyComponentLoader {
public IRegistration Load(string key, Type service)
{
if (service == null)
return null;
if (service.Name.EndsWith("ViewModel", StringComparison.CurrentCultureIgnoreCase))
return Component.For(service).Named(key);
else
return null;
}
}