Creating a DbContext in a Message Handler

I have a dll that exposes a type type

public class MyDbContext {
    [...]
}

inside this library I also have an implementation IPackagethat registers MyDbContextin a container, for example

public void RegisterServices( Container container ) {
    container.Register<MyDbContext>( Lifestyle.Scoped );
}

This assembly then refers to two different types of applications: - web avi project - asp.net mvc application

This is the initialization of the web project api

var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
InitializeContainer( container );
container.RegisterWebApiControllers( GlobalConfiguration.Configuration );
container.Verify();

and this is mvc application initialization

var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
InitializeContainer( container );
container.RegisterMvcControllers( Assembly.GetExecutingAssembly() );
container.Verify();

When I receive a message from the Rebus queue (in the mvc application), the container tries to initialize a message handler like this

public class MyHandler : BaseMessageHandler, IHandleMessages<MyMessage>, IHandleMessages<IFailed<MyMessage>>
{
    public MyHandler( ILog logger, MyDbContext context ) {
        _logger = logger;
        _context = context;
    }
}

but i get an error

Rebus.Retry.ErrorTracking.InMemErrorTracker - 1 85feff07-01a6-4195-8deb-7c8f1b62ecc3: SimpleInjector.ActivationException: MyDbContext -, (-) .

at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration`1 registration)
at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration`1 registration, Scope scope)
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope)
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.Container.GetInstance[TService]()

Async Scoped Lifestyle mvc, .

+4
1

Rebus , -. , WebRequestLifestyle Rebus.

, . /.

, MVC, MVC WebRequestLifestyle `AsyncScopedLifestyle.

MVC :

container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
    defaultLifestyle: new AsyncScopedLifestyle(),
    fallbackLifestyle: new WebRequestLifestyle());

:

public sealed class AsyncScopedMessageHandler<T> : IHandleMessages<T>
{
    private readonly Container container;
    private readonly Func<IHandleMessages<T>> decorateeFactory;
    public AsyncScopedMessageHandler(Container container, Func<IHandleMessages<T>> factory)
    {
        this.container = container;
        this.decorateeFactory = factory;
    }
    public async Task Handle(T message) {
        using (AsyncScopedLifestyle.BeginScope(this.container)) {
            var decoratee = this.decorateeFactory.Invoke();
            await decoratee.Handle(message);
        }
    }
}

:

container.RegisterDecorator(
    typeof(IHandleMessages<>),
    typeof(AsyncScopedMessageHandler<>),
    Lifestyle.Singleton);

MVC, -API.

+3

Source: https://habr.com/ru/post/1675253/


All Articles