Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tombatron/e3ac126664862701d295e2af8bca3834 to your computer and use it in GitHub Desktop.
Save tombatron/e3ac126664862701d295e2af8bca3834 to your computer and use it in GitHub Desktop.
MediatR with Decorators.
using Autofac;
using Autofac.Features.Variance;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Xunit;
using System;
namespace MediatR.Decorator.Example
{
#region MediatR Query and Handler
public class Example : IRequest<string>
{
public string Message { get; set; }
}
public interface IDecorated { }
public class ExampleHandler : IRequestHandler<Example, string>, IDecorated
{
public string Handle(Example message)
{
return message.Message;
}
}
public interface IRequestHandlerDecorator<TQuery, TResult> : IRequestHandler<TQuery, TResult> where TQuery : IRequest<TResult> { }
public class ExampleDecorator : IRequestHandlerDecorator<Example, string>
{
private readonly IRequestHandler<Example, string> _inner;
public ExampleDecorator(IRequestHandler<Example, string> inner)
{
_inner = inner;
}
public string Handle(Example message)
{
var innerResult = _inner.Handle(message);
return $"({innerResult})";
}
}
#endregion
#region MediatR Handler - No Decorator
public class MediatRNoDecorators
{
[Fact]
public async Task ItCanExecuteHandlerWithNoDecorator()
{
var builder = new ContainerBuilder();
Helpers.BootstrapAutofac(builder);
using (var container = builder.Build())
{
var mediator = container.Resolve<IMediator>();
var query = new Example { Message = "Hello World" };
var result = await mediator.Send(query);
Assert.Equal("Hello World", result);
}
}
}
#endregion
#region MediatR Handler - Open Decorator
public class MediatROpenDecorator
{
[Fact]
public async Task ItCanExecuteHandlerWithOpenDecorator()
{
var builder = new ContainerBuilder();
Helpers.BootstrapAutofac(builder);
builder.RegisterType<ExampleHandler>().Named<IRequestHandler<Example, string>>("example");
builder.RegisterDecorator<IRequestHandler<Example, string>>(
(c, inner) => new ExampleDecorator(c.ResolveNamed<IRequestHandler<Example, string>>("example")), fromKey: "example"
);
using (var container = builder.Build())
{
var mediator = container.Resolve<IMediator>();
var query = new Example { Message = "Hello World" };
var result = await mediator.Send(query);
Assert.Equal("(Hello World)", result);
}
}
}
#endregion
#region Helpers
public static class Helpers
{
public static void BootstrapAutofac(ContainerBuilder builder)
{
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
//builder.RegisterType<ExampleHandler>();
builder.RegisterAssemblyTypes(typeof(Example).GetTypeInfo().Assembly).Where(t =>
!t.GetInterfaces().Any(i => i.IsClosedTypeOf(typeof(IRequestHandlerDecorator<,>)))
&&
t.GetInterfaces().Any(i => i.IsClosedTypeOf(typeof(IRequestHandler<,>))
|| i.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>))
|| i.IsClosedTypeOf(typeof(ICancellableAsyncRequestHandler<,>))
|| i.IsClosedTypeOf(typeof(INotificationHandler<>))
|| i.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>))
|| i.IsClosedTypeOf(typeof(ICancellableAsyncNotificationHandler<>))
)
)
.AsImplementedInterfaces();
builder.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t =>
{
object o;
return c.TryResolve(t, out o) ? o : null;
};
});
builder.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
}
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment