【问题标题】:Can someone explain how Castle Windsor is working in my app?有人可以解释 Castle Windsor 在我的应用程序中是如何工作的吗?
【发布时间】:2011-01-13 12:07:29
【问题描述】:

我已经开始使用 Castle Windsor,不知何故我的应用程序已全部启动并运行,但我并不真正了解它是如何工作的。不要让我参考文档,否则我不会在这里。

在我的 Global.asax.cs 我有这个:

private static IWindsorContainer container;

protected void Application_Start()
{
  AreaRegistration.RegisterAllAreas();
  RegisterRoutes(RouteTable.Routes);
  BootstrapContainer();
} 

protected void Application_End()
{
  container.Dispose();
}

private static void BootstrapContainer()
{
 container = new WindsorContainer()
                .Install(FromAssembly.This());

 var controllerFactory = new WindsorControllerFactory(container.Kernel);
 ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}

现在这是注册一个我理解的新控制器工厂。我认为从当前程序集安装 WindsorContainer 会注册所有安装程序,例如我有一个存储库安装程序。我假设在 Global.asax 中创建的容器已传递给安装程序。

public class RepositoriesInstaller : IWindsorInstaller
{
     public void Install(IWindsorContainer container, IConfigurationStore store)
    {

        container.Register(AllTypes.FromThisAssembly()
                 .Where(type => type.Name.EndsWith("Repository"))
                 .WithService.DefaultInterface()
                 .Configure(c => c.LifeStyle.PerWebRequest));
    }
}

在我的控制器中,我创建了一个构造函数并传入了一个 IRepository 参数。我不明白的是控制器如何接受这个论点。

其次,作为测试,我创建了 2 个实现 IRepository 的存储库类。在控制器构造函数中放置一个断点,它会传入这些类之一。如何映射实现 IRepository 的类应该传递给构造函数?

我还启动并运行了 Fluent NHibernate。对于下一阶段,我希望 IRepository 依赖于 ISession。我该怎么做?

感谢您的帮助

【问题讨论】:

    标签: asp.net-mvc nhibernate fluent-nhibernate inversion-of-control castle-windsor


    【解决方案1】:

    由于您已经注册了一个使用 Windsor 的控制器工厂,因此 Windsor IoC 容器负责在需要时解析所有控制器实例。

    也就是说,当您访问 MVC 项目中指向“HomeController”上的操作“Index”的 URL 时,MVC 框架将向 WindsorControllerFactory 询问 HomeController 的实例。

    如果该控制器有一个构造函数,该构造函数采用 IRepository 的实例并且您已将 IRepository 注册为容器的服务,那么 Windsor 将知道如何满足 HomeController 类的依赖关系。因此,它可以先将 IRepository 解析为某个具体的类,将其实例化,并将其作为参数传递给 HomeController 构造函数,然后再将 HomeController 的实例返回给 MVC 框架。

    如果您出于不同目的需要不同的 IRepository 实现(即 UserRepository 和 ProductRepository),您可以为它们创建单独的接口,每个接口都扩展 IRepository,例如:

    public interface IProfileRepository : IRepository {}
    

    然后您可以使用 Windsor 的 fluent 注册 API 来注册所有实现 IRepository 的具体类,并让它们通过它们提供的特定服务进行注册,例如IProfileRepository。

    如果您这样做,Windsor 将自动为您解析所有实现 IRepository 的实例,而无需您在添加新实现时编写任何新的注册代码。

    至于使您的存储库类依赖于 ISession,您可以通过多种方式做到这一点。我建议不要让它们直接依赖于会话,而是让它们依赖于可以获取当前会话的类(以便您可以在存储库之间共享会话)。网上有很多关于为什么这是良好做法的信息,只需进行搜索即可。

    现在,至于真正实现它,您可以:

    • 注册一个类的实例(通过接口),它将为您检索与 Windsor 的会话,并让 Windsor 将该类作为参数解析给您的存储库构造函数。

    • 向 Windsor 注册 ISession,并在解决时使用工厂方法检索它。

    【讨论】:

    • 非常好的回复,谢谢,但是我有 2 个问题。在我的存储库安装程序中,它注册了所有存储库。出于好奇,我创建了 2 个实现相同 IRepository 的类。在构造函数中,Windsor 显然决定发送其中一个类。是什么决定的,为什么不选择其他类?我认为我最好将存储库映射到类,而不是我现在正在做的通用方法。
    • 我也遵循了关于公开 ISession bit.ly/gEokB1 的本教程,然后我在实现 IRepository 的类中创建了一个具有 ISession 参数的构造函数。你觉得可以接受吗?谢谢
    • 先回答你的最后一个问题:是的,这很好。在我的脑海中,我认为每次解析存储库时都会为您提供一个新的 ISession 实例(我可能错了!)这不一定是理想的 - 您可能希望在多个存储库之间共享一个 ISession 实例以提高性能好处。我会看看是否可以找到有关此信息的链接,但一般的想法是在 HttpContext.Items[] 中创建和存储一个 ISession - 并为每个 IRepository 重用该实例(这实际上是每个 ISession网络请求)。
    • 回答您的第一个问题:Windsor 将始终返回服务的第一个注册组件。如果您使用两个不同的具体类注册 IRepository,它将始终选择第一个。这就是为什么我建议为每个存储库使用不同的接口,它们都实现了 IRepository。这样,您可以拥有一个注册语句,它选择所有实现 IRepository 的类,并将它们注册到自己的服务(例如 UserRepository)。
    • 要注册 IRepository 的所有实例,您可以使用如下代码: container.Register(AllTypes.FromAssemblyNamed(_assemblyName).Pick() .If(t => t.FindInterfaces((t1, o) => t1.Name == "IRepository", null).Length > 0) .BasedOn(typeof (IRepository)) .WithService .FromInterface(typeof (IRepository)) .Configure(c => c.LifeStyle.瞬态));
    猜你喜欢
    • 2011-09-12
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    相关资源
    最近更新 更多