私は Castle n00b で、Castle Windsor の Fluent API を使用して、命名規則に基づいて実装をサービスに自動登録しています (ISomething は Something によって実装されています)。私がサポートしたかったことの 1 つは、自動登録が個別の dll にある依存関係を取得し、それらも自動登録することです。
つまり、IFoo は Foo (どちらも Foo.dll 内) によって実装され、Foo は Bar.dll 内の IBar に依存します。
自動登録を実際に実行するために、次のコードを記述しました。うまくいきそうですが、自分で頑張りすぎたのか気になります。同じことを達成するためのより簡単な方法はありますか?
private static void EnsureRegistered(Type t, IWindsorContainer container)
{
if (!container.Kernel.HasComponent(t) && (!(t.Assembly.FullName.StartsWith("System") || t.Assembly.FullName.StartsWith("mscorlib"))))
{
bool registeredAtLeastOneComponent = false;
container.Register(AllTypes.Pick().
FromAssembly(t.Assembly).If(delegate(Type t2)
{
//auto-registers all types that implement an interface where
//the name of the interface is the same as the class, minus the 'I'
//ex: EchoService is auto-registered as handler of IEchoService
Type[] interfaces = t2.GetInterfaces();
bool shouldRegister = false;
foreach(Type interfaceType in interfaces)
{
shouldRegister = t2.Name.Equals(interfaceType.Name.Substring(1))
&& (!container.Kernel.HasComponent(interfaceType));
registeredAtLeastOneComponent = registeredAtLeastOneComponent || shouldRegister;
if (shouldRegister)
break;
}
return shouldRegister;
}).WithService.Select(delegate(Type type, Type baseType)
{
Type serviceType = null;
Type[] interfaces = type.GetInterfaces();
foreach(Type interfaceType in interfaces)
{
if (!type.Name.Equals(interfaceType.Name.Substring(1))) continue;
serviceType = interfaceType;
break;
}
return new Type[] {serviceType};
}));
if (!registeredAtLeastOneComponent)
return;
//for each of the items in the graph, if they have see if they have dependencies
//in other assemblies that aren't registered, register those dependencies as well
foreach(GraphNode registered in container.Kernel.GraphNodes)
{
if (!(registered is Castle.Core.ComponentModel))
continue;
Castle.Core.ComponentModel registeredComponent = registered as Castle.Core.ComponentModel;
foreach(ConstructorCandidate constructor in registeredComponent.Constructors)
{
foreach(DependencyModel dep in constructor.Dependencies)
{
EnsureRegistered(dep.TargetType, container);
}
}
}
}
}