【问题标题】:Setup Castle Windsor in MVC在 MVC 中设置温莎城堡
【发布时间】:2013-11-02 14:52:14
【问题描述】:

我第一次尝试设置 Castle Windsor,但遇到了一些问题。我的解决方案中有三个项目:

  • DAL
  • 网络

服务位于 DAL。它们都继承自IService。 (UserService 实现 IUserServiceIUserService 实现 IService)。 Web 应用程序是一个 MVC 5 应用程序。所有控制器都继承自BaseController

我使用 this 帖子帮助我设置 Windsor,但我不断收到异常:

Castle.Windsor.dll 中出现“Castle.MicroKernel.ComponentNotFoundException”类型的异常,但未在用户代码中处理

附加信息:未找到支持服务 Solution.Web.Controllers.HomeController 的组件

奇怪的是控制器的路径是正确的。

下面是我的配置代码:

public class WindsorControllerFactory : DefaultControllerFactory
{
  private readonly IKernel kernel;

  public WindsorControllerFactory(IKernel kernel)
  {
    this.kernel = kernel;
  }

  public override void ReleaseController(IController controller)
  {
    kernel.ReleaseComponent(controller);
  }

  protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
  {
    if (controllerType == null)
    {
      throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
    }
    return (IController)kernel.Resolve(controllerType);
  }
}

public class ControllersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
          Classes.FromThisAssembly()
          .BasedOn(typeof(BaseController))
          .LifestyleTransient());
    }
}

public class ServiceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Types.FromAssemblyContaining(typeof(IService).GetType())
            .BasedOn<IService>().WithService.FromInterface()
            .LifestyleTransient()
        );
    }
}

在 Global.asax 中:

public class MvcApplication : System.Web.HttpApplication
{

    private static IWindsorContainer container;

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // Setup Castle.Windsor IOC
        MvcApplication.BootstrapContainer();
    }
    protected void Application_End()
    {
        container.Dispose();
    }

    private static void BootstrapContainer()
    {
        container = new WindsorContainer().Install(FromAssembly.This());
        container.Install(FromAssembly.Containing(typeof(IService).GetType()));
        var controllerFactory = new WindsorControllerFactory(container.Kernel);
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }
}

非常感谢任何正确方向的帮助或指导!

【问题讨论】:

    标签: c# asp.net-mvc castle-windsor


    【解决方案1】:

    我假设它在这里爆炸了:

    return (IController)kernel.Resolve(controllerType);
    

    您在这里用英语要求城堡做的是“给我实现由 controllerType 定义的服务的组件”。

    问题在于您的控制器注册。

    container.Register(
          Types.FromThisAssembly()
          .BasedOn(typeof(BaseController))
          .WithServices(typeof(BaseController))
          .LifestyleTransient());
    

    在这个块中,您告诉 Castle 注册所有实现 BaseController 的类型,并且它们公开的服务也是 BaseController。

    所以 castle 正在寻找一个满足 HomeController 服务的组件,但找不到任何东西,因为您拥有的唯一服务是 BaseController。

    长话短说,如果你删除

    .WithServices(typeof(BaseController))
    

    Castle 将假定您的每个控制器都是一个服务,然后您可以请求以您想要的方式实现您的控制器的组件。

    作为单独的说明,为了清楚起见,我会将 Types.FromThisAssembly() 更改为 Classes.FromThisAssembly() 因为您只在寻找 Types 将扫描的类,而不是结构/类/接口等。

    【讨论】:

    • 我已按照您的建议进行了更改,但我不断收到相同的错误。感谢Castle的详细解释:)
    【解决方案2】:

    我成功了。显然问题是我的服务没有注册。我更改了 ServiceInstaller 和 Global.asax 中的注册。

    public class ServiceInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromAssemblyContaining<BaseService>()
                .BasedOn(typeof(IService))
                .WithService.AllInterfaces()
                .LifestyleTransient());            
        }
    }
    
    private static void BootstrapContainer()
    {
        container = new WindsorContainer();
        container.Install(new ServiceInstaller());
        container.Install(new ControllersInstaller());
    
        var controllerFactory = new WindsorControllerFactory(container.Kernel);
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }
    

    【讨论】:

    • 很高兴它现在可以工作了。您最终是否不得不更改您的控制器注册?
    • 不,控制器的注册是正确的。再次感谢您的提示和解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多