I'm a Castle n00b, and am using the Fluent API in Castle Windsor to auto-register implementations to services based on a naming convention (ISomething is implemented by Something). One thing I wanted to support is for auto-registration to pick up dependencies that are in separate dlls, and auto-register those, as well.
So: IFoo is implemented by Foo (both in Foo.dll), and Foo depends on IBar, which is in Bar.dll.
I have the following code written to actually perform the auto-registration. It seems to work, but I'm wondering whether I did too much work myself. Is there a simpler way to accomplish the same thing?
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);
}
}
}
}
}