Резольвер зависимости Виндзорского замка для MVC 3 - PullRequest
32 голосов
/ 10 ноября 2010

Поскольку реализация IoC / DI в MVC 3, скорее всего, в окончательном виде в RC, я ищу обновленную реализацию DependencyResolver, IControllerActivator и IViewPageActivator с использованием Caste Windsor.Есть ли какие-нибудь примеры, которые были обновлены для MVC 3 RC?

EDIT # 1 Реализация средства разрешения зависимостей Виндзора действительно тривиальна, но кое-чего еще не хватает.В отличие от примера Джеффа Путца Ninject (ниже), кажется, что это не так просто, как в случае с Windsor.После установки преобразователя зависимостей следующим образом:

DependencyResolver.SetResolver(new WindsorDependencyResolver(container)); 

Windsor создает исключение ComponentNotFoundException.Мне нужно предоставить реализации для IControllerFactory и IControllerActivator.Поскольку DefaultControllerFactory поддерживает DependencyResolver, это можно решить следующим образом:

Component.For<IControllerFactory >().ImplementedBy<DefaultControllerFactory>()
Component.For<IControllerActivator >().ImplementedBy<WindsorControllerActivator>(),

WindsorControllerActivator также тривиален.Однако это приводит к другому исключению ComponentNotFoundException для IViewPageActivator.

Это приводит меня к мысли, что я что-то упустил.Нет способа сделать это более сложным, чем реализация фабрики контроллеров и вызов ControllerBuilder.Current.SetControllerFactory в стиле MVC 2.0.

EDIT # 2 Я пропустил тонкую, но важную детальчто распознаватель зависимостей должен возвращать ноль, когда служба не может быть найдена.Реализация выглядит следующим образом:

public class WindsorDependencyResolver : IDependencyResolver
{
    private readonly IWindsorContainer container;

    public WindsorDependencyResolver(IWindsorContainer container)
    {
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        return container.Kernel.HasComponent(serviceType) ? container.Resolve(serviceType) : null;
    }

  public IEnumerable<object> GetServices(Type serviceType)
    {
        return container.Kernel.HasComponent(serviceType) ? container.ResolveAll(serviceType).Cast<object>() : new object[]{};
    }
}

EDIT # 3

Ответ на вопрос в комментариях.Если вы обнаружите, что вам нужен собственный IControllerActivator, вот простая реализация для Windsor:

public class WindsorControllerActivator : IControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorControllerActivator(IWindsorContainer container)
    {
        this.container = container;
    }

    public IController Create(RequestContext requestContext, Type controllerType)
    {
        return (IController)container.GetService(controllerType);
    }
}

}

Опять же, НЕ необходимо для получения базового DIработа с Windsor и средством разрешения зависимостей MVC3.

EDIT # 4 Основываясь на некоторых дальнейших исследованиях и отзывах, кажется, что традиционная реализация фабрики контроллеров - лучший подход для Windsor и MVC3.Проблема заключается в том, что в интерфейсе IDependencyResolver отсутствует метод освобождения, который может привести к утечкам памяти, если Windsor не удаляет свои компоненты.Это, вероятно, не будет проблемой, если все ваши зависимости будут решены с помощью жизненного цикла PerWebRequest, но все же лучше не рисковать.Вот базовая реализация фабрики контроллеров Windsor для MVC3.

public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IWindsorContainer container;

    public WindsorControllerFactory(IWindsorContainer container)
    {
        this.container = container;
    }

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

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controllerComponentName = controllerName + "Controller";
        return container.Kernel.Resolve<IController>(controllerComponentName);
    }
}

РЕДАКТИРОВАТЬ # 5 Если вы используете области MVC, вышеуказанная реализация не будет работать для вас.Вам нужно будет зарегистрировать каждый контроллер на основе его полного имени и переопределить GetControllerInstance вместо CreateController:

 protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType != null)
        {
            return (IController)container.Kernel.Resolve(controllerType);
        }
        return null;
    }

Ответы [ 3 ]

24 голосов
/ 03 февраля 2011

Интерфейс MVC3 IDependencyResolver имеет большую проблему: нет метода выпуска.Это означает, что существует потенциальная утечка памяти, если вы собираетесь использовать ее с Windsor.Смотрите мой блог об этом здесь:

http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html

10 голосов
/ 10 ноября 2010

Интерфейс не изменился со времени бета-версии, поэтому все реализации для различных фреймворков все еще должны работать.И правда в том, что интерфейс не так уж и сложен ... вы должны быть в состоянии развернуть свой собственный без особых хлопот.Например, я сделал это для Ninject:

public class NinjectDependencyResolver : IDependencyResolver
{
    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    private readonly IKernel _kernel;

    public object GetService(Type serviceType)
    {
        return _kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _kernel.GetAll(serviceType);
    }
}

Затем подключите его в global.asax так:

    private static IKernel _kernel;
    public IKernel Kernel
    {
        get { return _kernel; }
    }

    public void Application_Start()
    {
        _kernel = new StandardKernel(new CoreInjectionModule());
        DependencyResolver.SetResolver(new NinjectDependencyResolver(Kernel));
        ...
    }

Помните, вы получаете все виды вкусностей бесплатно наэта точка, включая DI для контроллеров, фабрики контроллеров, фильтры действий и базовые классы представления.

РЕДАКТИРОВАТЬ: Чтобы было ясно, я не уверен, что ваши "активаторы", но они, вероятно, вам не нужны,Интерфейс IDependencyResolver автоматически выполняет обновление контроллеров и представлений.

2 голосов
/ 10 ноября 2010

MVCContrib в настоящее время является официальным источником для интеграции IoC-MVC. В настоящее время ветвь MVC3 включает в себя только фабрику контроллеров и реализации IDependencyResolver (и пару других вещей). Я рекомендую разветвить хранилище и реализовать недостающие точки расширения (не должно быть слишком сложно), а затем отправить команде запрос на извлечение.

...