Настройка инверсии управления (IoC) в ASP.NET MVC с помощью Castle Windsor - PullRequest
8 голосов
/ 26 февраля 2011

Я расскажу о ASP.NET MVC Framework Сандерсона и в главе 4 он обсуждает Создание фабрики пользовательских контроллеров , и кажется, что оригинальный метод AddComponentLifeStyle или AddComponentWithLifeStyle использовался для регистрация контроллеров устарела:

public class WindsorControllerFactory : DefaultControllerFactory
{
    IWindsorContainer container;

    public WindsorControllerFactory()
    {
        container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));

        // register all the controller types as transient
        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        //[Obsolete("Use Register(Component.For<I>().ImplementedBy<T>().Named(key).Lifestyle.Is(lifestyle)) instead.")]
        //IWindsorContainer AddComponentLifeStyle<I, T>(string key, LifestyleType lifestyle) where T : class;
        foreach (Type t in controllerTypes)
        {
            container.Register(Component.For<IController>().ImplementedBy<???>().Named(t.FullName).LifeStyle.Is(LifestyleType.Transient));
        }
    }

    // Constructs the controller instance needed to service each request
    protected override IController GetControllerInstance(Type controllerType)
    {
        return (IController)container.Resolve(controllerType);
    }
}

Новое предложение заключается в использовании Register(Component.For<I>().ImplementedBy<T>().Named(key).Lifestyle.Is(lifestyle)), но я не могу понять, как представить реализующий тип контроллера в методе ImplementedBy<???>(). Я пробовал ImplementedBy<t>() и ImplementedBy<typeof(t)>(), но не могу найти подходящий способ передачи в типе реализации. Есть идеи?

Ответы [ 5 ]

6 голосов
/ 26 февраля 2011

Я делаю это, используя ControllerBuilder.SetControllerFactory и код, который вы можете найти в проекте с открытым исходным кодом MvcContrib :

Global.asax.cs

protected void Application_Start()
{
    ...

    IWindsorContainer windsorContainer = new WindsorContainer();
    windsorContainer.RegisterControllers(Assembly.GetExecutingAssembly());
    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(windsorContainer));

    ...
}

WindsorControllerFactory

public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IWindsorContainer _container;

    public WindsorControllerFactory(IWindsorContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException();
        }

        _container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException();
        }

        if (!typeof(IController).IsAssignableFrom(controllerType))
        {
            throw new ArgumentException();
        }

        try
        {
            return (IController)_container.Resolve(controllerType);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException();
        }
    }

    public override void ReleaseController(IController controller)
    {
        IDisposable disposable = controller as IDisposable;

        if (disposable != null)
        {
            disposable.Dispose();
        }

        _container.Release(controller);
    }
}

WindsorExtensions (см. MvcContrib )

public static class WindsorExtensions
{
    public static IWindsorContainer RegisterController<T>(this IWindsorContainer container) where T : IController
    {
        container.RegisterControllers(typeof(T));

        return container;
    }

    public static IWindsorContainer RegisterControllers(this IWindsorContainer container, params Type[] controllerTypes)
    {
        foreach (Type type in controllerTypes)
        {
            if (ControllerExtensions.IsController(type))
            {
                container.Register(Component.For(type).Named(type.FullName).LifeStyle.Is(LifestyleType.Transient));
            }
        }

        return container;
    }

    public static IWindsorContainer RegisterControllers(this IWindsorContainer container, params Assembly[] assemblies)
    {
        foreach (Assembly assembly in assemblies)
        {
            container.RegisterControllers(assembly.GetExportedTypes());
        }

        return container;
    }
}

ControllerExtensions (см. MvcContrib )

public static class ControllerExtensions
{
    public static bool IsController(Type type)
    {
        return type != null
               && type.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)
               && !type.IsAbstract
               && typeof(IController).IsAssignableFrom(type);
    }
}
2 голосов
/ 26 февраля 2011

Вы также можете рассмотреть возможность использования новой опции установщика в последней сборке Windsor. Есть больше документации по учебнику Виндзора: http://stw.castleproject.org/Windsor.Windsor-tutorial-part-three-writing-your-first-installer.ashx

1 голос
/ 26 февраля 2011

@ Lirik, в качестве дополнения: оставьте свой собственный IControllerFactory, если вы используете MVC3.Просто зарегистрируйте контроллеры в Windsor и внедрите IDependencyResolver с контейнером Windsor внутри.

Установите IDependencyResolver как MVC DependencyResolver, и DefaultControllerFactory автоматически подключит контроллеры, зарегистрированные в контейнере (через DependencyResolver).

1 голос
/ 26 февраля 2011

Есть учебник (в работе, но 9 частей уже вышли), в котором обсуждается использование Windsor в ASP.NET MVC здесь .Насколько мне известно, это самая актуальная информация, которая охватывает большую часть обычного ресурса использования по этой теме.

0 голосов
/ 26 февраля 2011

что-то вроде:

public void Register(IWindsorContainer container)
    {
        Assembly.GetAssembly(typeof(ControllersRegistrarMarker)).GetExportedTypes()
                .Where(IsController)
                .Each(type => container.AddComponentLifeStyle(
                                      type.Name.ToLower(),
                                      type,
                                      LifestyleType.Transient));
    }

ControllersRegistrarMarker - это просто пустой класс в вашей сборке Controllers

...