Castle Windsor:主控制器无法解析容器中的已注册组件

时间:2010-09-15 15:06:31

标签: model-view-controller asp.net-mvc-2 castle-windsor ioc-container sessionfactory

在我的Global.asax.cs中有下面的代码和两个控制器(一个基于另一个:MasterController)我似乎没有找到如何从MasterController解析我的WindsorContainer中的存储库寄存器...这同样适用于HomeController并且完美地工作......我做错了什么?

的Global.asax.cs:

private IWindsorContainer _container;

protected void Application_Start()
{
    InitializeContainer();
    RegisterRoutes(RouteTable.Routes);
}

protected void Application_End()
{
    this._container.Dispose();
}

protected void Application_EndRequest()
{
    if (_container != null)
    {
        var contextManager = _container.Resolve<IContextManager>();
        contextManager.CleanupCurrent();
    }
}

private void InitializeContainer()
{
    _container = new WindsorContainer();

    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));

    // Register context manager.
    _container.Register(
        Component.For<IContextManager>()
        .ImplementedBy<EFContextManager>()
        .LifeStyle.Singleton
        .Parameters(
            Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
        )
    );

        //Products repository           
    _container.Register(
        Component.For<IProductRepository>()
        .ImplementedBy<ProductRepository>()
        .LifeStyle.Singleton
    );

    // Register all MVC controllers
    _container.Register(AllTypes.Of<IController>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Configure(c => c.LifeStyle.Transient)
    );

}

控制器基础:

public class MasterController : Controller
{
    private IProductRepository _productRepository;

    public ProductController(IProductRepository product)
    {
        _productRepository = product;
    }

    public ActionResult Index()
    {
       ViewData["product"] = _productRepository.FindOne(123);   
       return View();
    }
}

基于MasterController的控制器:

public class ProductController : MasterController
{
    private IProductRepository _productRepository;

    public ProductController(IProductRepository product)
    {
        _productRepository = product;
    }

    public ActionResult Search(int id)
    {
       ViewData["product"] = _productRepository.FindOne(id);    
       return View();
    }
}

1 个答案:

答案 0 :(得分:1)

它正在按预期工作,并且可以从任何控制器/视图访问ViewDatas。

首先,我创建了一个公共类,用于存储我的Windsor容器,以便可以从任何控制器访问它:

public static class IOCcontainer
{
    public static IWindsorContainer Container { get; set; }
}

然后在我的global.asax.cs中我有:

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

private void InitializeContainer()
{
    _container = new WindsorContainer();

    // Register context manager.
    _container.Register(
        Component.For<IContextManager>()
        .ImplementedBy<EFContextManager>()
        .LifeStyle.Singleton
        .Parameters(
            Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
        )
    );

        //Products repository           
    _container.Register(
        Component.For<IProductRepository>()
        .ImplementedBy<ProductRepository>()
        .LifeStyle.Singleton
    );

    // Register all MVC controllers
    _container.Register(AllTypes.Of<IController>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Configure(c => c.LifeStyle.Transient)
    );

    IOCcontainer.Container = _container; //set the container class with all the registrations

    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}

所以现在在我的主控制器中我可以使用:

public class MasterController : Controller
{

    private IProductRepository g_productRepository;

    public MasterController() : this(null,null,null,null,null)
    {
    }

    public MasterController(IProductRepository productRepository)
    {
        g_productRepository = productRepository ?? IOCcontainer.Container.Resolve<IProductRepository>();
    }

    //I don't use an action here, this will make execute it for any action in any controller
    protected override void OnActionExecuting(ActionExecutingContext context)
    {   
        if (!(context.ActionDescriptor.ActionName.Equals("Index") && context.Controller.ToString().IndexOf("Home")>0)) {
        //I now can use this viewdata to populate a dropdownlist along the whole application
        ViewData["products"] = g_productRepository.GetProducts().ToList().SelectFromList(x => x.Id.ToString(), y => y.End.ToShortDateString());
        }
    }
}

然后是其他控制器:

//will be based on MasterController
public class AboutController : MasterController 
{

}

public ActionResult Index()
{
    return View();
}

etc...

可能不是最优雅的方式,但它会发现,直到我找到更好的方式或其他人照亮我的想法!