Как правильно добавить конструктор / свойства в ASP.NET HttpModule с помощью простого инжектора

1

У меня есть класс под названием UsersOnlineModule, который создается из IHttpModul. В этом классе я хотел бы ввести два свойства, которые я использовал, для этого я использую Simple Injector.

public class UsersOnlineModule
{
    public ITenantStore tenantStore;
    public ICacheManager cm;

Я вызываю этот класс из IHttpModule:

Modules.UsersOnline.UsersOnlineModule usersOnlineModule =
    new Modules.UsersOnline.UsersOnlineModule();
usersOnlineModule.TrackUser(app.Context);

Однако мой IHttpModule не знает о менеджере кэша или tenantStore. Я могу решить это, получив объекты из контейнера, однако я бы предпочел не создавать ссылку на Simple Injector. Есть ли другой хороший вариант для разрешения этих двух свойств без создания ссылок на мой контейнер?

-- Обновить

Я изменил пример следующим образом:

class ImportAttributePropertySelectionBehavior : IPropertySelectionBehavior
{
    public bool SelectProperty(Type serviceType, PropertyInfo propertyInfo)
    {
        return typeof(IHttpModule).IsAssignableFrom(serviceType) &&
            propertyInfo.GetCustomAttributes<ImportAttribute>().Any();
    }
}

private static void RegisterHttpModules(Container container)
{
    var httpModules =
        from assembly in BuildManager.GetReferencedAssemblies().Cast<Assembly>()
        where !assembly.IsDynamic
        where !assembly.GlobalAssemblyCache
        from type in assembly.GetExportedTypes()
        where type.IsSubclassOf(typeof(IHttpModule))
        select type;

    httpModules.ToList().ForEach(container.Register);
}

но он не возвращает ни одного из моих httpmodules.

Теги:
dependency-injection
simple-injector

1 ответ

2
Лучший ответ

Руководство по интеграции показывает, как использовать HttpModule для инициализации HttpHandlers. Однако HttpModule не создается для каждого запроса; он создается один раз для приложения и регистрируется в событиях HttpApplication когда вызывается его метод инициализации.

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

public class UsersOnlineModule : IHttpModule
{
    public void Init(HttpApplication context) {
        context.PreRequestHandlerExecute += (s, e) => {
            var handler = Global.GetInstance<UsersOnlineHandler>();
            handler.Handle();
        };
    }
}

В этом примере UsersOnlineModule делает не что иное, как разрешение одной единственной службы и вызов ее метода на ней. Эта служба (UsersOnlineHandler в этом случае) должна UsersOnlineHandler всю необходимую логику и зависимости. Другими словами, ваш HttpModule становится Humble Object, и вся логика извлекается в UsersOnlineHandler:

public class UsersOnlineHandler
{
    private readonly ITenantStore tenantStore;
    private readonly ICacheManager cm;

    public UsersOnlineHandler(ITenantStore tenantStore, ICacheManager cm) {
        this.tenantStore = tenantStore;
        this.cm = cm;
    }

    public void Handle() {
       // logic here
    }
}

ПРЕДУПРЕЖДЕНИЕ. Обязательно не храните никаких зависимостей в поля класса или экземпляра или свойства вашего HttpModule, потому что это может привести к тому, что зависимость станет Captive Dependency. Вместо этого, как описано выше, просто разрешите, используйте и забудьте об этой зависимости, все внутри этого вызова метода. Не храните его.

  • 0
    Привет, Стивен, я посмотрел на это, но я не понимаю, как это делает мои IHttpModules слабо связанными, так как теперь модули должны знать о моем объекте MvcApplication для динамической регистрации?
  • 0
    Хитрость заключается в том, что вы создаете один HttpModule, который тесно связан с DI-контейнером и является частью корневого каталога композиции. И с этим единственным модулем HttpModule вы можете добавить множество других модулей HttpModule, которые вообще не зависят от контейнера. Они просто используют атрибут (самостоятельно определяемый или .NET Framework), который отмечает свойство для внедрения.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню