|
1 | 1 | namespace NServiceBus.Testing |
2 | 2 | { |
3 | 3 | using System; |
| 4 | + using System.Collections.Generic; |
4 | 5 | using System.Linq; |
5 | 6 | using System.Linq.Expressions; |
6 | 7 | using System.Threading.Tasks; |
7 | | - |
| 8 | + |
8 | 9 | static class TypeExtensions |
9 | 10 | { |
10 | | - public static Func<object, object, IMessageHandlerContext, Task> CreateInvoker(this Type targetType, Type messageType, Type interfaceGenericType) |
| 11 | + public static IEnumerable<Func<object, object, IMessageHandlerContext, Task>> CreateInvokers(this Type targetType, Type messageType, Type interfaceGenericType) |
11 | 12 | { |
12 | | - var interfaceType = interfaceGenericType.MakeGenericType(messageType); |
13 | | - |
14 | | - if (!interfaceType.IsAssignableFrom(targetType)) |
| 13 | + var interfaceTypes = targetType.GetInterfaces() |
| 14 | + .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == interfaceGenericType) |
| 15 | + .Where(i => i.GenericTypeArguments.First().IsAssignableFrom(messageType)); |
| 16 | + |
| 17 | + foreach (var interfaceType in interfaceTypes) |
15 | 18 | { |
16 | | - return null; |
17 | | - } |
18 | | - |
19 | | - var methodInfo = targetType.GetInterfaceMap(interfaceType).TargetMethods.FirstOrDefault(); |
20 | | - if (methodInfo == null) |
21 | | - { |
22 | | - return null; |
23 | | - } |
24 | | - |
25 | | - var target = Expression.Parameter(typeof(object)); |
26 | | - var messageParam = Expression.Parameter(typeof(object)); |
27 | | - var contextParam = Expression.Parameter(typeof(IMessageHandlerContext)); |
28 | | - |
29 | | - var castTarget = Expression.Convert(target, targetType); |
30 | | - |
31 | | - var methodParameters = methodInfo.GetParameters(); |
32 | | - var messageCastParam = Expression.Convert(messageParam, methodParameters.ElementAt(0).ParameterType); |
33 | | - |
34 | | - Expression body = Expression.Call(castTarget, methodInfo, messageCastParam, contextParam); |
35 | | - |
36 | | - return Expression.Lambda<Func<object, object, IMessageHandlerContext, Task>>(body, target, messageParam, contextParam).Compile(); |
| 19 | + var methodInfo = targetType.GetInterfaceMap(interfaceType).TargetMethods.FirstOrDefault(); |
| 20 | + if (methodInfo == null) |
| 21 | + { |
| 22 | + yield break; |
| 23 | + } |
| 24 | + |
| 25 | + var target = Expression.Parameter(typeof(object)); |
| 26 | + var messageParam = Expression.Parameter(typeof(object)); |
| 27 | + var contextParam = Expression.Parameter(typeof(IMessageHandlerContext)); |
| 28 | + |
| 29 | + var castTarget = Expression.Convert(target, targetType); |
| 30 | + |
| 31 | + var methodParameters = methodInfo.GetParameters(); |
| 32 | + var messageCastParam = Expression.Convert(messageParam, methodParameters.ElementAt(0).ParameterType); |
| 33 | + |
| 34 | + Expression body = Expression.Call(castTarget, methodInfo, messageCastParam, contextParam); |
| 35 | + |
| 36 | + yield return Expression.Lambda<Func<object, object, IMessageHandlerContext, Task>>(body, target, messageParam, contextParam).Compile(); |
| 37 | + } |
37 | 38 | } |
| 39 | + |
| 40 | + public static async Task InvokeSerially(this IEnumerable<Func<object, object, IMessageHandlerContext, Task>> invokers, object instance, object message, IMessageHandlerContext context) |
| 41 | + { |
| 42 | + foreach (var invocation in invokers) |
| 43 | + { |
| 44 | + await invocation(instance, message, context).ConfigureAwait(false); |
| 45 | + } |
| 46 | + } |
38 | 47 | } |
39 | | - } |
| 48 | + } |
0 commit comments