我们有一个解决方案,其中多个项目代表我们的应用程序层。 e.g。
域
数据
逻辑
WebUI中
我们的Castle Windsor容器是从我们的网络层引用的,然后我们将这些依赖项级联到层。例如......
// In Domain
public interface IFooRepository
{
void DoSomething();
}
// In Data
public class FooRepository : IFooRepository
{
public void DoSomething()
{
// Something is done
}
}
// In Logic
public class MyThingManager
{
private readonly IFooRepository fooRepository;
public MyThingManager(IFooRepository fooRepository)
{
this.fooRepository = fooRepository;
}
public void AMethod()
{
this.fooRepository.DoSomething();
}
}
// In Web
// in some controller....
var newManager = new MyThingManager(WindsorContainer.Resolve<IFooRepository>());
newManager.DoSomething();
这很好用,直到我们的经理有很多成员有自己的依赖。当这种情况发生时,我们最终解决了管理者的依赖性和他们的依赖性,并将其从Web层级联起来。这个结果是一些相当大的构造函数。
是否有更优雅的方式,例如让经理的内部组件解决它自己的依赖性而无法访问容器?
请记住,只有web层才能访问容器(以防止循环项目依赖),所以只有web层可以激活WindsorContainer.Resolve()逻辑层不能这样才能级联a没有容器帮助的依赖性是在Web层中解析它,然后使用它的接口将其传递给链。
答案 0 :(得分:6)
简短的回答是,只要您看到.Resolve<T>
,就可能doing it wrong。正如@Steven所提到的,您希望使用Windsor的内置功能为您提供构造函数注入(和/或属性注入)。这意味着WindsorContainer
需要知道对象图根的对象。
在您的情况下,您将走向对象树(从MyThingyManager
)直到您到达根对象。例如,在ASP.NET MVC应用程序中,这将是包含被调用操作的控制器。对于MVC3案例,您将使用DependencyResolver启动所有依赖项的注入。
此外,我发现过去与Windsor一起使用的是每个组件(组件)具有不同的安装程序。然后在托管应用程序的进程的基础上注册这些安装程序。
因此,在每个组件中,您将拥有如下安装程序:
public class Installer : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(
Component.For<IMyThingManager>().ImplementedBy<MyThingManager>(),
Component.For<IFooRepository>().ImplementedBy<FooRepository>()
);
}
}
然后在Global.asax.cs Application_Start中你会有类似的东西:
var container = new WindsorContainer();
container.Install(FromAssembly.This());
container.Install(FromAssembly.Containing(typeof(ComponentThatContains.MyThingManager.Installer)));
这为您提供了一种管理整个对象图中所有依赖关系并通过构造函数注入解决的方法。 希望这会有所帮助。