Answer the question
In order to leave comments, you need to log in
C#: How to correctly configure Autofac for Domain events dispatcher?
Good afternoon!
When implementing Domain events, I use
the event itself:
public class ProductCreatedEvent : IDomainEvent
{
public Product Product { get; }
public ProductCreatedEvent(Product product)
{
Product = product;
}
}
public class EmailCustomerOnProductCreatedHandler : IDomainEventHandler<ProductCreatedEvent>
{
private readonly ILogger _logger;
public EmailCustomerOnProductCreatedHandler(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.Create(GetType());
}
public void Handle(ProductCreatedEvent @event)
{
_logger.Trace($"Send email to customer: Product \"{@event.Product.ProductName}\" was created.");
}
}
public class AutofacDomainEventDispatcher : IDomainEventDispatcher
{
private readonly ILifetimeScope _container;
public AutofacDomainEventDispatcher(ILifetimeScope container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public void Dispatch<TDomainEvent>(TDomainEvent @event) where TDomainEvent : IDomainEvent
{
// Для тестов я пока просто пытаюсь получить КОНЕКРЕТНЫЙ обработчик
var handler = _container.Resolve<IDomainEventHandler<ProductCreatedEvent>>();
handler.Handle(@event as ProductCreatedEvent); // Привожу к ProductCreatedEvent только для теста
}
}
public static class Bootstrapper
{
public static void Setup()
{
var builder = new ContainerBuilder();
// Регистрируем фабрику для логгеров
builder.RegisterType(typeof(NLoggerFactory)).As(typeof(ILoggerFactory)).InstancePerRequest();
// Регистрируем конкретный обработчик
builder
.RegisterType(typeof(EmailCustomerOnProductCreatedHandler))
.As(typeof(IDomainEventHandler<ProductCreatedEvent>))
.InstancePerLifetimeScope();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Setup DomainEventDispatcher
DomainEventDispatcherProvider.Setup(new AutofacDomainEventDispatcher(container));
}
}
var handler = _container.Resolve<IDomainEventHandler<ProductCreatedEvent>>();
DependencyResolutionException: Unable to resolve the type 'ElibraryEngine.CrossCutting.Logging.NLog.NLoggerFactory' because the lifetime scope it belongs in can't be located. The following services are exposed by this registration:
- ElibraryEngine.CrossCutting.Logging.ILoggerFactory
If you see this during execution of a web application, it generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario). Under the web integration always request dependencies from the dependency resolver or the request lifetime scope, never from the container itself.
.InstancePerLifetimeScope()
, but .InstancePerRequest()
, then the exception is like this:DependencyResolutionException: No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question