views:

111

answers:

1

Suppose I have a dependency that is registered as HttpRequestScoped so there is only one instance per request. How could I resolve a dependency of the same type outside of an HttpRequest?

For example:

// Global.asax.cs Registration
builder.Register(c => new MyDataContext(connString)).As<IDatabase>().HttpRequestScoped();
_containerProvider = new ContainerProvider(builder.Build());

// This event handler gets fired outside of a request
// when a cached item is removed from the cache.
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
    // I'm trying to resolve like so, but this doesn't work...
    var dataContext = _containerProvider.ApplicationContainer.Resolve<IDatabase>();
    // Do stuff with data context.
}

The above code throws a DependencyResolutionException when it executes the CacheItemRemoved handler:

No scope matching the expression 'value(Autofac.Builder.RegistrationBuilder`3+<>c__DisplayClass0[MyApp.Core.Data.MyDataContext,Autofac.Builder.SimpleActivatorData,Autofac.Builder.SingleRegistrationStyle]).lifetimeScopeTag.Equals(scope.Tag)' is visible from the scope in which the instance was requested.

+2  A: 

InstancePerLifetimeScope(), rather than HttpRequestScoped(), will give the result you need.

There is a caveat though - if IDatabase requires disposal, or depends on something that requires disposal, this won't happen if you resolve it from the ApplicationContainer. Better to do:

using (var cacheRemovalScope =
        _containerProvider.ApplicationContainer.BeginLifetimeScope())
{
    var dataContext = cacheRemovalScope.Resolve<IDatabase>();
    // Do what y' gotta do...
}

Cheers, Nick

Nicholas Blumhardt
This works, but for some reason, none of my changes are persisted back to the database when I make this change.
Page Brooks
Since you're outside of an HTTP request, any request pipeline additions you've made will not be executed; chances are there's a transaction you need to commit somewhere.
Nicholas Blumhardt