Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using System.Reflection;
13 : using Akka.Actor;
14 : using cdmdotnet.Logging;
15 : using Cqrs.Akka.Events;
16 : using Cqrs.Bus;
17 : using Cqrs.Commands;
18 : using Cqrs.Configuration;
19 : using Cqrs.Events;
20 : using Cqrs.Messages;
21 :
22 : namespace Cqrs.Akka.Configuration
23 : {
24 : /// <summary>
25 : /// Triggers the <see cref="BusRegistrar"/> instantiates instances of <see cref="IEventHandler{TAuthenticationToken, TEvent}"/> and <see cref="ICommandHandler{TAuthenticationToken,TCommand}"/> classes that inherit the akka.net <see cref="ReceiveActor"/> via the <see cref="IDependencyResolver"/> so their message registration kicks in.
26 : /// </summary>
27 : public class AkkaBusRegistrar<TAuthenticationToken> : BusRegistrar
28 1 : {
29 : /// <summary>
30 : /// Gets or sets the <see cref="IHandlerResolver"/>.
31 : /// </summary>
32 : protected IHandlerResolver HandlerResolver { get; private set; }
33 :
34 : /// <summary>
35 : /// Instantiates a new instance of <see cref="AkkaBusRegistrar{TAuthenticationToken}"/>.
36 : /// </summary>
37 1 : public AkkaBusRegistrar(IDependencyResolver dependencyResolver, IHandlerResolver handlerResolver)
38 : : base(dependencyResolver)
39 : {
40 : HandlerResolver = handlerResolver;
41 : }
42 :
43 : #region Overrides of BusRegistrar
44 :
45 : /// <summary>
46 : /// Builds a <see cref="HandlerDelegate"/> that will resolve the provided <paramref name="executorType"/> and invoke the Handle method, when executed.
47 : /// </summary>
48 : /// <param name="executorType">The type of <see cref="IHandler"/> to resolve.></param>
49 : /// <param name="resolveMessageHandlerInterface">Not used.</param>
50 1 : protected override HandlerDelegate BuildDelegateAction(Type executorType, Func<Type, IEnumerable<Type>> resolveMessageHandlerInterface)
51 : {
52 : Type targetedType = executorType;
53 : Type @interface = resolveMessageHandlerInterface(executorType).FirstOrDefault();
54 : if (@interface != null && @interface.GenericTypeArguments.Length > 2)
55 : targetedType = executorType.GenericTypeArguments[1];
56 :
57 : Action<dynamic> handlerDelegate = x =>
58 : {
59 : dynamic handler;
60 : try
61 : {
62 : Type messageType = ((object)x).GetType();
63 : object rsn = messageType.GetProperty("Rsn").GetValue(x, null);
64 : handler = HandlerResolver.Resolve(executorType, rsn);
65 : }
66 : catch (Exception)
67 : {
68 : handler = DependencyResolver.Resolve(executorType);
69 : }
70 : IActorRef actorReference = handler as IActorRef;
71 : try
72 : {
73 : if (actorReference != null)
74 : actorReference.Tell((object)x);
75 : else
76 : handler.Handle(x);
77 : }
78 : catch (NotImplementedException exception)
79 : {
80 : var logger = DependencyResolver.Resolve<ILogger>();
81 : logger.LogInfo(string.Format("An event message arrived of the type '{0}' went to a handler of type '{1}' but was not implemented.", x.GetType().FullName, handler.GetType().FullName), exception: exception);
82 : }
83 : };
84 :
85 : // Instantiate an instance so it triggers the constructor with it's registrations
86 : DependencyResolver.Resolve(executorType);
87 :
88 : return new HandlerDelegate { Delegate = handlerDelegate, TargetedType = targetedType };
89 : }
90 :
91 : /// <summary>
92 : /// Invokes <paramref name="handlerDelegate"/>, fetching the corresponding "HoldMessageLock" configuration setting
93 : /// </summary>
94 : /// <param name="registerExecutorMethod">The <see cref="MethodInfo"/> to use to invoke <paramref name="handlerDelegate"/>.</param>
95 : /// <param name="trueForEventsFalseForCommands">Indicates if this is registers <see cref="IEventHandler"/> or <see cref="ICommandHandler{TAuthenticationToken,TCommand}"/>.</param>
96 : /// <param name="handlerDelegate">The actual <see cref="HandlerDelegate"/> that gets executed.</param>
97 1 : protected override void InvokeHandlerDelegate(MethodInfo registerExecutorMethod, bool trueForEventsFalseForCommands, HandlerDelegate handlerDelegate)
98 : {
99 : base.InvokeHandlerDelegate(registerExecutorMethod, trueForEventsFalseForCommands, handlerDelegate);
100 : registerExecutorMethod.Invoke(DependencyResolver.Resolve<IAkkaEventPublisher<TAuthenticationToken>>(), new object[] { handlerDelegate.Delegate, handlerDelegate.TargetedType });
101 : }
102 :
103 : #endregion
104 : }
105 : }
|