2

I have a class called UsersOnlineModule that is being created from an IHttpModul. Within this class I would like to have two properties injected, I'm using Simple Injector for this.

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

I'm calling this class from an IHttpModule:

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

However my IHttpModule does not know about the cache manager or tenantStore. I can solve this by getting the objects from the container, however I would prefer not to create a reference to Simple Injector. Is there any other nice option to resolve these two properties without creating references to my container?

-- Update

I modified the example as follows:

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);
}

but it's not returning any of my httpmodules.

0

1 Answer 1

3

The integration guide shows how to use a HttpModule to initialize HttpHandlers. A HttpModule however doesn't get created per request; it is created once for the application and will register to the HttpApplication's events when its initialize method is called.

Since a module is a singleton, you should not inject dependencies into your module. You should resolve dependencies per request, and since the HttpModule can't be configured and is not a dependency of its own, you will have to call back into the container from within your HttpModule. There's really no other way, but the trick here is to minimize the amount of code needed. Example:

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

In this example, the UsersOnlineModule does do nothing more than resolving one single service and call its method on it. This service (UsersOnlineHandler in this case) should capture all logic and dependencies needed. So in other words, your HttpModule becomes a Humble Object and all logic is extracted into the 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
    }
}

WARNING: Be sure not to store any dependencies into class or instance fields or properties of your HttpModule, because that might cause a dependency to become a Captive Dependency. Instead, as described above, just resolve, use, and forget about that dependency, all inside that method call. Do not store it.

Sign up to request clarification or add additional context in comments.

7 Comments

Hi Steven, I looked at this, but I don't see how it makes my IHttpModules loosely coupled as now the modules need to know about my MvcApplication object to register themselves dynamically?
The trick is that you make one HttpModule that is tightly coupled to the DI container and is part of the composition root. And with this single HttpModule you can add many other HttpModules that have no dependency on the container at all. They just use an attribute (self-defined or by the .NET framework) that marks a property for injection.
ahh, makes more sense. I just modified the example to look at IHttpModules instead of Page as I'm using MVC, however i did not get it to work.. i'll try some more tomorrow.
ok, im lost now, I have modified all, however I'm getting exceptions now on the MvcHandler in the init method, and my HttpModule properties are not getting injected..... sigh, I guess I will end up with using the container in my module....
@user3188048: I'm sorry, I mislead you. Please see my update.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.