У меня есть класс под названием 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.
Руководство по интеграции показывает, как использовать 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. Вместо этого, как описано выше, просто разрешите, используйте и забудьте об этой зависимости, все внутри этого вызова метода. Не храните его.