Dependency injection 温莎城堡与自动注册
我是Castle n00b,正在使用Castle Windsor中的Fluent API根据命名约定自动注册服务的实现(ISomething由某物实现)。我想支持的一件事是自动注册来获取独立DLL中的依赖项,并自动注册这些依赖项 所以:IFoo是由Foo(都在Foo.dll中)实现的,而Foo依赖于Bar.dll中的IBar 我编写了以下代码来实际执行自动注册。这似乎有效,但我想知道我自己是否做了太多的工作。有没有更简单的方法来完成同样的事情Dependency injection 温莎城堡与自动注册,dependency-injection,inversion-of-control,castle-windsor,Dependency Injection,Inversion Of Control,Castle Windsor,我是Castle n00b,正在使用Castle Windsor中的Fluent API根据命名约定自动注册服务的实现(ISomething由某物实现)。我想支持的一件事是自动注册来获取独立DLL中的依赖项,并自动注册这些依赖项 所以:IFoo是由Foo(都在Foo.dll中)实现的,而Foo依赖于Bar.dll中的IBar 我编写了以下代码来实际执行自动注册。这似乎有效,但我想知道我自己是否做了太多的工作。有没有更简单的方法来完成同样的事情 private static void Ensure
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);
}
}
}
}
}
这实际上取决于您如何构造和命名组件。。。如果保留一些简单约定(即“MyApp.services”命名空间下的所有组件服务及其“MyApp.services.Impl”下的实现),则可以显著降低这种复杂性(例如,请参见)
此外,除最简单的情况外,这种方法的实用性相当有限。。。例如,您希望在没有任何服务接口的情况下注册某些服务,某些服务需要配置、服务覆盖等。在这种情况下,这将不起作用。不确定这是否回答了您的问题,但这是我为自动注册服务所做的
// Auto-Register Services as Singletons
container.Register(
AllTypes.FromAssembly(typeof(BaseService).Assembly).Pick()
.WithService.DefaultInterfaces()
.Configure(s => s.LifestyleSingleton()));
我的所有服务都继承自一个BaseService(抽象类)和一个接口IService。这将自动将具体服务类绑定到其接口,并使其可在容器中使用。谢谢您的回答。我正在做的是在一些遗留应用程序中引入一个容器,并在使用容器时追求零摩擦(只要它们符合“IBar由Bar实现”的约定)。并同意:复杂场景。不过,我想打80%的案子,谢谢。就像我说的,我主要是想看看我是否错过了一个更简单的方法。正如您所指出的,简化事情的一种方法是简化容器周围的事情:-)