如何使用Simple Injector在ASP.NET HttpModule中正确地注入构造函数/属性

时间:2014-11-16 15:54:33

标签: c# asp.net dependency-injection simple-injector

我有一个名为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。

1 个答案:

答案 0 :(得分:2)

integration guide显示如何使用 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)应捕获所需的所有逻辑和依赖项。换句话说,您的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。相反,如上所述,只需解决,使用和忘记该依赖关系,所有这些都在该方法调用中。不要存储它。