Created
February 18, 2016 18:09
-
-
Save dannyc02/f8d2cb03115262e85b8d to your computer and use it in GitHub Desktop.
CQRS with generic types
This file contains 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 FluentAssertions; | |
using MediatR; | |
using NUnit.Framework; | |
using StructureMap; | |
using StructureMap.Graph; | |
using StructureMap.Graph.Scanning; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Container = StructureMap.Container; | |
namespace MediatorTests | |
{ | |
[TestFixture] | |
public class UnitTest1 | |
{ | |
public class HomeItem : IItem | |
{ | |
} | |
[Test] | |
public void ShouldResolveGenericHandler() | |
{ | |
var container = new Container(cfg => | |
{ | |
cfg.Scan(scanner => | |
{ | |
scanner.TheCallingAssembly(); | |
scanner.IncludeNamespaceContainingType<HomeItem>(); | |
scanner.AddAllTypesOf(typeof(IRequestHandler<,>)); | |
scanner.With(new AddRequestHandlersWithGenericParametersToRegistry()); | |
scanner.WithDefaultConventions(); | |
}); | |
cfg.For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t)); | |
cfg.For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => ctx.GetAllInstances(t)); | |
cfg.For<IMediator>().Use<Mediator>(); | |
}); | |
var mediator = container.GetInstance<IMediator>(); | |
Console.Write(container.WhatDoIHave()); | |
var response = mediator.Send(new CreateItemCommand<HomeItem>()); | |
var response2 = mediator.Send(new CreateHomeItemCommand()); | |
response.Should().NotBeNull(); | |
response2.Should().NotBeNull(); | |
} | |
} | |
public class CreateHomeItemCommand : IRequest<UnitTest1.HomeItem> | |
{ | |
} | |
public class CreateHomeItemCommandHandler : IRequestHandler<CreateHomeItemCommand, UnitTest1.HomeItem> | |
{ | |
public UnitTest1.HomeItem Handle(CreateHomeItemCommand message) | |
{ | |
return new UnitTest1.HomeItem(); | |
} | |
} | |
public class CreateItemCommand<T> : IRequest<T> where T : IItem | |
{ | |
} | |
public class CreateItemCommandHandler<T> : IRequestHandler<CreateItemCommand<T>, T> where T : IItem | |
{ | |
public T Handle(CreateItemCommand<T> message) | |
{ | |
return Activator.CreateInstance<T>(); | |
} | |
} | |
public class AddRequestHandlersWithGenericParametersToRegistry : IRegistrationConvention | |
{ | |
public void ScanTypes(TypeSet types, Registry registry) | |
{ | |
var commandMappings = GetRequestHandlersWithGenericParameters(types); | |
foreach (var commandMapping in commandMappings) | |
{ | |
foreach (var concreteClass in types.FindTypes(TypeClassification.Concretes)) | |
{ | |
if (concreteClass.GetInterfaces().Contains(typeof(IItem))) | |
{ | |
var genericCommand = commandMapping.Command.MakeGenericType(concreteClass); | |
var interfaceHandlerType = typeof(IRequestHandler<,>).MakeGenericType(genericCommand, concreteClass); | |
var concreteHandlerType = commandMapping.Handler.MakeGenericType(concreteClass); | |
registry.For(interfaceHandlerType).Use(concreteHandlerType); | |
} | |
} | |
} | |
} | |
private IEnumerable<CommandMapping> GetRequestHandlersWithGenericParameters(TypeSet types) | |
{ | |
foreach (var concreteType in types.FindTypes(TypeClassification.Concretes)) | |
{ | |
var genericInterfaces = concreteType.GetInterfaces().Where(x => x.IsGenericType); | |
foreach (var genericInterface in genericInterfaces) | |
{ | |
if (genericInterface.GetGenericTypeDefinition() == typeof (IRequestHandler<,>)) | |
{ | |
var requestHandlerType = concreteType; | |
var commandParameterType = genericInterface.GetGenericArguments()[0]; | |
if (commandParameterType.IsGenericType) | |
{ | |
yield return new CommandMapping { Command = commandParameterType.GetGenericTypeDefinition(), Handler = requestHandlerType }; | |
} | |
} | |
} | |
} | |
} | |
} | |
public class CommandMapping | |
{ | |
public Type Handler { get; set; } | |
public Type Command { get; set; } | |
} | |
public interface IItem | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment