/
Program.cs
138 lines (117 loc) · 5.86 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using MediatR.Pipeline;
using Unity;
using Unity.Lifetime;
namespace MediatR.Examples.Unity
{
internal class Program
{
private static Task Main(string[] args)
{
var writer = new WrappingWriter(Console.Out);
var mediator = BuildMediator(writer);
writer.WriteLine("Unity is not a very good container and breaks immediately");
return Runner.Run(mediator, writer, "Unity");
}
private static IMediator BuildMediator(WrappingWriter writer)
{
var container = new UnityContainer();
container.RegisterInstance<TextWriter>(writer)
.RegisterMediator(new HierarchicalLifetimeManager())
.RegisterMediatorHandlers(Assembly.GetAssembly(typeof(Ping)));
container.RegisterType(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>), "RequestPreProcessorBehavior");
container.RegisterType(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>), "RequestPostProcessorBehavior");
container.RegisterType(typeof(IPipelineBehavior<,>), typeof(GenericPipelineBehavior<,>), "GenericPipelineBehavior");
container.RegisterType(typeof(IRequestPreProcessor<>), typeof(GenericRequestPreProcessor<>), "GenericRequestPreProcessor");
container.RegisterType(typeof(IRequestPostProcessor<,>), typeof(GenericRequestPostProcessor<,>), "GenericRequestPostProcessor");
container.RegisterType(typeof(IRequestPostProcessor<,>), typeof(ConstrainedRequestPostProcessor<,>), "ConstrainedRequestPostProcessor");
// Unity doesn't support generic constraints
//container.RegisterType(typeof(INotificationHandler<>), typeof(ConstrainedPingedHandler<>), "ConstrainedPingedHandler");
return container.Resolve<IMediator>();
}
}
// ReSharper disable once InconsistentNaming
public static class IUnityContainerExtensions
{
public static IUnityContainer RegisterMediator(this IUnityContainer container, ITypeLifetimeManager lifetimeManager)
{
return container.RegisterType<IMediator, Mediator>(lifetimeManager)
.RegisterInstance<ServiceFactory>(type =>
{
var enumerableType = type
.GetInterfaces()
.Concat(new[] { type })
.FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));
return enumerableType != null
? container.ResolveAll(enumerableType.GetGenericArguments()[0])
: container.IsRegistered(type)
? container.Resolve(type)
: null;
});
}
public static IUnityContainer RegisterMediatorHandlers(this IUnityContainer container, Assembly assembly)
{
return container.RegisterTypesImplementingType(assembly, typeof(IRequestHandler<,>))
.RegisterNamedTypesImplementingType(assembly, typeof(INotificationHandler<>));
}
internal static bool IsGenericTypeOf(this Type type, Type genericType)
{
return type.IsGenericType &&
type.GetGenericTypeDefinition() == genericType;
}
internal static void AddGenericTypes(this List<object> list, IUnityContainer container, Type genericType)
{
var genericHandlerRegistrations =
container.Registrations.Where(reg => reg.RegisteredType == genericType);
foreach (var handlerRegistration in genericHandlerRegistrations)
{
if (list.All(item => item.GetType() != handlerRegistration.MappedToType))
{
list.Add(container.Resolve(handlerRegistration.MappedToType));
}
}
}
/// <summary>
/// Register all implementations of a given type for provided assembly.
/// </summary>
public static IUnityContainer RegisterTypesImplementingType(this IUnityContainer container, Assembly assembly, Type type)
{
foreach (var implementation in assembly.GetTypes().Where(t => t.GetInterfaces().Any(implementation => IsSubclassOfRawGeneric(type, implementation))))
{
var interfaces = implementation.GetInterfaces();
foreach (var @interface in interfaces)
container.RegisterType(@interface, implementation);
}
return container;
}
/// <summary>
/// Register all implementations of a given type for provided assembly.
/// </summary>
public static IUnityContainer RegisterNamedTypesImplementingType(this IUnityContainer container, Assembly assembly, Type type)
{
foreach (var implementation in assembly.GetTypes().Where(t => t.GetInterfaces().Any(implementation => IsSubclassOfRawGeneric(type, implementation))))
{
var interfaces = implementation.GetInterfaces();
foreach (var @interface in interfaces)
container.RegisterType(@interface, implementation, implementation.FullName);
}
return container;
}
private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var currentType = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == currentType)
return true;
toCheck = toCheck.BaseType;
}
return false;
}
}
}