using System.Threading.Tasks;
using System.Collections.Generic;
namespace PerEventHandlerScope
public static void Main()
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules( typeof( HandlerModule ).Assembly );
builder.RegisterType<Mediator>().As<IMediator>().InstancePerLifetimeScope();
builder.RegisterType<ADatabaseContext>().AsSelf().InstancePerMatchingLifetimeScope( "PerHandlerKey" );
var container = builder.Build();
var pingHandler = container.Resolve<IAsyncRequestHandler<PingRequest, PingResponse>>();
var pingResponse = pingHandler.Handle( new PingRequest() ).Result;
Console.WriteLine( pingResponse.ToString() );
public class HandlerModule : Autofac.Module
protected override void Load( ContainerBuilder builder )
builder.RegisterAssemblyTypes( ThisAssembly )
.Where( interfaceType => interfaceType.IsClosedTypeOf( typeof( IAsyncRequestHandler<,> ) ) ) )
.AsImplementedInterfaces().InstancePerLifetimeScope();
List<Type> eventHandlerTypes = new List<Type>();
var assemblies = new[] { ThisAssembly }
foreach ( var assembly in assemblies )
var types = assembly.GetTypes().Where( t => t.IsClosedTypeOf( typeof( IAsyncNotificationHandler<> ) ) );
eventHandlerTypes.AddRange( types );
ISet<Type> notificationTypes = new HashSet<Type>();
foreach ( var eventHandlerType in eventHandlerTypes )
var interfaces = eventHandlerType
var interfaceType = interfaces
.First( i => i.IsClosedTypeOf( typeof( IAsyncNotificationHandler<> ) ) );
var notificationType = interfaceType.GenericTypeArguments.Single();
builder.RegisterType( eventHandlerType )
.Named( "EventHandler", eventHandlerType )
.InstancePerMatchingLifetimeScope( "PerHandlerKey" );
Type factoryType = typeof( EventHandlerFactory<,> );
Type[] typeParams = new Type[] { notificationType, eventHandlerType };
Type constructedFactoryType = factoryType.MakeGenericType( typeParams );
builder.RegisterType( constructedFactoryType ).AsSelf().AsImplementedInterfaces().SingleInstance();
if ( !notificationTypes.Contains( notificationType ) )
Type decoratorType = typeof( LifetimeScopeHandlerDecorator<> );
Type constructedType = decoratorType.MakeGenericType( notificationType );
builder.RegisterType( constructedType ).Named( "EventHandlerDecorator", interfaceType ).AsSelf().InstancePerLifetimeScope();
notificationTypes.Add( notificationType );
builder.Register<SingleInstanceFactory>( ctx =>
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve( t );
).InstancePerLifetimeScope();
builder.Register<MultiInstanceFactory>( ctx =>
var c = ctx.Resolve<IComponentContext>();
MultiInstanceFactory result = t =>
var genericType = typeof( IEnumerable<> ).MakeGenericType( t );
var instances = (IEnumerable<object>)c.ResolveKeyed( "EventHandlerDecorator", genericType );
int count = instances.Count();
Console.WriteLine( String.Format( "instances {0}", count ) );
).InstancePerLifetimeScope();
public class PingRequest : IAsyncRequest<PingResponse>
public class PingResponse
public class Pinged : IAsyncNotification
public class PingHandler : IAsyncRequestHandler<PingRequest, PingResponse>
private readonly IMediator _mediator;
public PingHandler( IMediator mediator )
public async Task<PingResponse> Handle( PingRequest request )
Console.WriteLine( "PingHandler" );
await _mediator.PublishAsync( new Pinged() );
Console.WriteLine( "PingHandler after publish" );
return new PingResponse();
public class ADatabaseContext
public class PingedHandler1 : IAsyncNotificationHandler<Pinged>
private readonly ADatabaseContext _context;
public PingedHandler1( ADatabaseContext context )
public async Task Handle( Pinged notifiaction )
Console.WriteLine( String.Format( "{0} handled by Ping Handler 1", _context.DoWork() ) );
await Task.CompletedTask;
public class PingedHandler2 : IAsyncNotificationHandler<Pinged>
private readonly ADatabaseContext _context;
public PingedHandler2( ADatabaseContext context )
public async Task Handle( Pinged notifiaction )
Console.WriteLine( String.Format( "{0} handled by Ping Handler 2", _context.DoWork() ) );
await Task.CompletedTask;
public interface IEventHandlerFactory<in TNotification> where TNotification : class, IAsyncNotification
IAsyncNotificationHandler<TNotification> Create( ILifetimeScope lifetimeScope );
public class EventHandlerFactory<TNotification, TEventHandler> : IEventHandlerFactory<TNotification>
where TNotification : class, IAsyncNotification
where TEventHandler : class, IAsyncNotificationHandler<TNotification>
public IAsyncNotificationHandler<TNotification> Create( ILifetimeScope lifetimeScope )
return lifetimeScope.ResolveNamed<TEventHandler>( "EventHandler" ) as IAsyncNotificationHandler<TNotification>;
public class LifetimeScopeHandlerDecorator<TNotification> : IAsyncNotificationHandler<TNotification> where TNotification : class, IAsyncNotification
private readonly ILifetimeScope _scope;
public LifetimeScopeHandlerDecorator( ILifetimeScope scope )
public async Task Handle( TNotification notification )
Console.WriteLine( "LifetimeScopeDecoratorHandler" );
_scope.Resolve<IEnumerable<IEventHandlerFactory<TNotification>>>();
foreach ( var handlerFactory in handlerFactories )
using ( var perHandlerScope = _scope.BeginLifetimeScope( "PerHandlerKey" ) )
var innerHandler = handlerFactory.Create( perHandlerScope );
Console.WriteLine( String.Format( "{0}", innerHandler.GetType().FullName ) );
await innerHandler.Handle( notification );