Last active
May 19, 2017 18:22
-
-
Save tombatron/80b7ac3077655541606f0080802d8d90 to your computer and use it in GitHub Desktop.
Setup MediatR, with "decorator" support.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Autofac; | |
using Autofac.Features.Variance; | |
using MediatR; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
namespace Mediatr.Extras.Autofac | |
{ | |
public static class AutofacExtensions | |
{ | |
private static readonly Type[] MediatRTypes = new[] | |
{ | |
typeof(IRequestHandler<>), | |
typeof(IRequestHandler<,>), | |
typeof(IAsyncRequestHandler<>), | |
typeof(IAsyncRequestHandler<,>), | |
typeof(ICancellableAsyncRequestHandler<>), | |
typeof(ICancellableAsyncRequestHandler<,>), | |
typeof(INotificationHandler<>), | |
typeof(IAsyncNotificationHandler<>), | |
typeof(ICancellableAsyncNotificationHandler<>), | |
}; | |
public static void RegisterMediatR(this ContainerBuilder @this, Assembly[] assemblies, Action<ContainerBuilder> preMediatRRegistration = null) | |
{ | |
preMediatRRegistration?.Invoke(@this); | |
foreach (var assembly in assemblies) | |
{ | |
RegisterMediatRHandlers(@this, assembly); | |
} | |
RegisterMediatRFactories(@this); | |
} | |
private static void RegisterMediatRFactories(ContainerBuilder builder) | |
{ | |
builder.RegisterSource(new ContravariantRegistrationSource()); | |
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).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)); | |
}); | |
} | |
private static void RegisterMediatRHandlers(ContainerBuilder builder, Assembly assembly) | |
{ | |
var types = assembly.GetTypes() | |
.Where(t => t.GetInterfaces() | |
.Any(i => MediatRTypes | |
.Any(x => i.IsClosedTypeOf(x)))); | |
builder.RegisterTypes(types.ToArray()) | |
.PreserveExistingDefaults() | |
.AsImplementedInterfaces(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Autofac; | |
using MediatR; | |
using MediatR.Extras.Autofac.TestAssembly; | |
using System.Reflection; | |
using System.Threading.Tasks; | |
using Xunit; | |
using Xunit.Abstractions; | |
namespace Mediatr.Extras.Autofac.Tests | |
{ | |
public class AutofacExtensionsTests | |
{ | |
private static readonly Assembly TestAssembly = Assembly.Load("MediatR.Extras.Autofac.TestAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); | |
public class ItCanRegister | |
{ | |
public class IRequestHandlers | |
{ | |
[Fact] | |
public void WithOneGenericTypeParameterCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new RequestWithNoResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
[Fact] | |
public void WithTwoGenericTypeParametersCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new RequestWithResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
} | |
public class IAsyncRequestHandlers | |
{ | |
[Fact] | |
public void WithOneGenericTypeParameterCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new AsyncRequestWithNoResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
[Fact] | |
public void WithTwoGenericTypeParametersCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new AsyncRequestWithResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
} | |
public class ICancellableAsyncRequestHandlers | |
{ | |
[Fact] | |
public void WithOneGenericTypeParameterCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new CancellableAsyncRequestWithNoResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
[Fact] | |
public void WithTwoGenericTypeParametersCorrectly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var request = new CancellableAsyncRequestWithResult(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Send(request); | |
} | |
} | |
} | |
public class INotificationHandlers | |
{ | |
[Fact] | |
public void Correctly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var notification = new ExampleNotification(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Publish(notification); | |
} | |
} | |
} | |
public class IAsyncNotificationsHandlers | |
{ | |
[Fact] | |
public void Correctly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var notification = new ExampleAsyncNotification(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Publish(notification); | |
} | |
} | |
} | |
public class ICancellableAsyncNotificationHandlers | |
{ | |
[Fact] | |
public void Correctly() | |
{ | |
using (var scope = GetAutofacScope()) | |
{ | |
var notification = new ExampleCancellableAsyncNotification(); | |
var mediatr = scope.Resolve<IMediator>(); | |
mediatr.Publish(notification); | |
} | |
} | |
} | |
} | |
public class ItCanDecorate | |
{ | |
private readonly ITestOutputHelper _output; | |
public ItCanDecorate(ITestOutputHelper output) | |
{ | |
_output = output; | |
} | |
[Fact] | |
public async Task AHandler() | |
{ | |
var builder = new ContainerBuilder(); | |
builder.RegisterMediatR(new[] { TestAssembly }, (b) => | |
{ | |
b.RegisterType<RequestWithResultHandler>() | |
.Named<IRequestHandler<RequestWithResult, string>>("example"); | |
b.RegisterDecorator<IRequestHandler<RequestWithResult, string>>( | |
(c, inner) => new TestDecorator1(inner), | |
fromKey: "example" | |
).Named<IRequestHandler<RequestWithResult, string>>("example_with_decorator_1"); | |
b.RegisterDecorator<IRequestHandler<RequestWithResult, string>>( | |
(c, inner) => new TestDecorator2(inner), | |
fromKey: "example_with_decorator_1" | |
); | |
}); | |
var container = builder.Build(); | |
using (var scope = container.BeginLifetimeScope()) | |
{ | |
var mediator = scope.Resolve<IMediator>(); | |
var result = await mediator.Send(new RequestWithResult()); | |
var result2 = await mediator.Send(new AsyncRequestWithResult()); | |
_output.WriteLine(result); | |
_output.WriteLine(result2); | |
} | |
} | |
} | |
private static ILifetimeScope GetAutofacScope() | |
{ | |
var builder = new ContainerBuilder(); | |
builder.RegisterMediatR(new[] { TestAssembly }); | |
var container = builder.Build(); | |
return container.BeginLifetimeScope(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment