Замок Виндзор: главный контроллер не разрешает зарегистрированные компоненты в контейнере - PullRequest
0 голосов
/ 15 сентября 2010

Имея приведенный ниже код в моем Global.asax.cs и два контроллера (один на основе другого: MasterController), я не вижу, как можно разрешить регистр хранилища в моем WindsorContainer из MasterController то же самое относится и к 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 Ответ

1 голос
/ 23 сентября 2010

Теперь он работает как положено, и 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...

Возможно, это не самый элегантный способ сделать это, но он будет работать до тех пор, пока я не найду лучший способ или кто-то еще не украсит мой разум!

...