Mvc 3/Unity 2 внедряет зависимости в фильтр?

Как я могу внедрить следующие зависимости??

public class Authenticate : AuthorizeAttribute
{
        [Dependency]
        public IAuthenticate AuthenticateLibrary { get; set; }

        [Dependency]
        public ILibrary BaseLibrary { get; set; }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
        }
}

Я использую Unity 2 для внедрения всех контроллеров. Есть ли учебник по Unity 2 и внедрению зависимостей в фильтры?


person Patrick    schedule 25.05.2011    source источник


Ответы (3)


У Брэда Уилсона есть хорошая серия статей о расположении службы, в которой рассказывается о том, как создать собственный поставщик фильтров, поддерживающий внедрение зависимостей: http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html (прокрутите вниз до раздела "Добавление внедрения зависимостей" к фильтрам").

  • Скопируйте код, который он предоставляет для UnityFilterAttributeFilterProvider.cs.

UnitFilterAttributeFilterProvider.cs

using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.Practices.Unity;

public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
    private IUnityContainer _container;

    public UnityFilterAttributeFilterProvider(IUnityContainer container) {
        _container = container;
    }

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(
                ControllerContext controllerContext,
                ActionDescriptor actionDescriptor) {

        var attributes = base.GetControllerAttributes(controllerContext,
                                                      actionDescriptor);
        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }

    protected override IEnumerable<FilterAttribute> GetActionAttributes(
                ControllerContext controllerContext,
                ActionDescriptor actionDescriptor) {

        var attributes = base.GetActionAttributes(controllerContext,
                                                  actionDescriptor);
        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }
}
  • Измените Application_Start файла global.asax.cs, чтобы сделать UnityFilterAttributeFilterProvider поставщиком фильтров для вашего приложения MVC.

.

protected void Application_Start() {
    // ...

    var oldProvider = FilterProviders.Providers.Single(
        f => f is FilterAttributeFilterProvider
    );
    FilterProviders.Providers.Remove(oldProvider);

    var container = new UnityContainer();
    var provider = new UnityFilterAttributeFilterProvider(container);
    FilterProviders.Providers.Add(provider);

    // ...
}
  • Украсьте свойства, для которых вы хотите, чтобы Unity внедрила значение, с помощью атрибута [Dependency]. И тогда вы должны быть готовы идти.
person John Allers    schedule 26.05.2011

Поскольку Unity не создает экземпляры фильтров, он не может их внедрить. Вам придется прибегнуть к шаблону локатора сервисов, например, в следующем:

public class Authenticate : AuthorizeAttribute
{
    public IAuthenticate AuthenticateLibrary { get; private set; }

    public ILibrary BaseLibrary { get; private set; }

    public Authenticate()
    {
        AuthenticateLibrary = DependencyResolver.Current.GetService<IAuthenticate>();
        BaseLibrary = DependencyResolver.Current.GetService<ILibrary >();
    }
    ...
}
person Ethan Cabiac    schedule 26.05.2011
comment
Если бы я добавил ILibrary и IAuthenticate к обычному контроллеру, они были бы созданы. Так что я знаю, что они зарегистрированы в единстве. - person Patrick; 26.05.2011
comment
@Patrick - дело не в том, зарегистрированы ли они, а в том, как они создаются. По сути, фреймворк вызывает new Authenticate(), который обходит любой DI-контейнер. - person Ethan Cabiac; 26.05.2011

Для всех людей, которые (как и я) прибыли сюда в поисках решения в MVC4 + Unity, хотя принятые ответы работают отлично, я хотел добавить, что теперь вы также можете просто переопределить метод GetFilters класса FilterAttributeFilterProvider:

public class CustomFilterProvider : FilterAttributeFilterProvider
{
    private readonly IUnityContainer container;

    public CustomFilterProvider(IUnityContainer container)
    {
        this.container = container;
    }

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(controllerContext, actionDescriptor);

        var enumerable = filters as IList<Filter> ?? filters.ToList();

        foreach (var filter in enumerable)
        {
            container.BuildUp(filter.Instance.GetType(), filter.Instance);
        }

        return enumerable;
    }
}

Ваше здоровье.

person Tallmaris    schedule 08.07.2013