Documentation Coverage Report
Current view: top level - Ninject/Cqrs.Ninject.Akka - AkkaNinjectDependencyResolver.cs Hit Total Coverage
Version: 2.2 Artefacts: 12 12 100.0 %
Date: 2017-09-22

          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.Concurrent;
      11             : using System.Collections.Generic;
      12             : using System.Linq;
      13             : using Akka.Actor;
      14             : using Cqrs.Akka.Configuration;
      15             : using Cqrs.Akka.Domain;
      16             : using Cqrs.Configuration;
      17             : using Cqrs.Domain;
      18             : using Cqrs.Domain.Factories;
      19             : using Cqrs.Ninject.Configuration;
      20             : using Ninject;
      21             : 
      22             : namespace Cqrs.Ninject.Akka
      23             : {
      24             :         /// <summary>
      25             :         /// Provides an ability to resolve instances of objects and Akka.NET objects using Ninject
      26             :         /// </summary>
      27             :         public class AkkaNinjectDependencyResolver
      28             :                 : NinjectDependencyResolver
      29             :                 , IAkkaAggregateResolver
      30             :                 , IAkkaSagaResolver
      31             :                 , IHandlerResolver
      32           1 :         {
      33             :                 /// <summary>
      34             :                 /// The inner resolver used by Akka.NET
      35             :                 /// </summary>
      36             :                 protected global::Akka.DI.Ninject.NinjectDependencyResolver RawAkkaNinjectDependencyResolver { get; set; }
      37             : 
      38             :                 /// <summary>
      39             :                 /// The <see cref="ActorSystem"/> as part of Akka.NET.
      40             :                 /// </summary>
      41             :                 protected ActorSystem AkkaSystem { get; private set; }
      42             : 
      43             :                 /// <summary>
      44             :                 /// A generic type, quick reference, lookup for fast resolving of Akka.NET objects since the patterns calls for them to be treated like statics
      45             :                 /// </summary>
      46             :                 protected IDictionary<Type, IActorRef> AkkaActors { get; private set; }
      47             : 
      48             :                 /// <summary>
      49             :                 /// The <see cref="IAggregateFactory"/> that will be used to create new instances of Akka.NET objects.
      50             :                 /// </summary>
      51             :                 protected IAggregateFactory AggregateFactory { get; private set; }
      52             : 
      53             :                 /// <summary>
      54             :                 /// Instantiates a new instance of <see cref="AkkaNinjectDependencyResolver"/>
      55             :                 /// </summary>
      56           1 :                 public AkkaNinjectDependencyResolver(IKernel kernel, ActorSystem system)
      57             :                         : base(kernel)
      58             :                 {
      59             :                         RawAkkaNinjectDependencyResolver = new global::Akka.DI.Ninject.NinjectDependencyResolver(kernel, AkkaSystem = system);
      60             :                         AkkaActors = new ConcurrentDictionary<Type, IActorRef>();
      61             :                         // ReSharper disable DoNotCallOverridableMethodsInConstructor
      62             :                         AggregateFactory = Resolve<IAggregateFactory>();
      63             :                         // ReSharper restore DoNotCallOverridableMethodsInConstructor
      64             :                 }
      65             : 
      66             :                 /// <summary>
      67             :                 /// Checks if an instance of <see cref="IDependencyResolver"/> is already registered, if one is registered, it in unregistered and this instance is registered as the <see cref="IDependencyResolver"/>.
      68             :                 /// It then checks if an instance of <see cref="IAkkaAggregateResolver"/> is already registered, if one is registered, it in unregistered and this instance is registered as the <see cref="IAkkaAggregateResolver"/>
      69             :                 /// </summary>
      70           1 :                 protected override void BindDependencyResolver()
      71             :                 {
      72             :                         bool isDependencyResolverBound = Kernel.GetBindings(typeof(IDependencyResolver)).Any();
      73             :                         if (isDependencyResolverBound)
      74             :                                 Kernel.Unbind<IDependencyResolver>();
      75             :                         Kernel.Bind<IDependencyResolver>()
      76             :                                 .ToConstant(this)
      77             :                                 .InSingletonScope();
      78             : 
      79             :                         isDependencyResolverBound = Kernel.GetBindings(typeof(IAkkaAggregateResolver)).Any();
      80             :                         if (!isDependencyResolverBound)
      81             :                         {
      82             :                                 Kernel.Bind<IAkkaAggregateResolver>()
      83             :                                         .ToConstant(this)
      84             :                                         .InSingletonScope();
      85             :                         }
      86             :                 }
      87             : 
      88             :                 /// <summary>
      89             :                 /// Starts the <see cref="AkkaNinjectDependencyResolver"/>
      90             :                 /// </summary>
      91             :                 /// <remarks>
      92             :                 /// This exists so the static constructor can be triggered.
      93             :                 /// </remarks>
      94           1 :                 public new static void Start(IKernel kernel = null, bool prepareProvidedKernel = false)
      95             :                 {
      96             :                         // Create the ActorSystem and Dependency Resolver
      97             :                         ActorSystem system = ActorSystem.Create("Cqrs");
      98             : 
      99             :                         Func<IKernel, NinjectDependencyResolver> originalDependencyResolverCreator = DependencyResolverCreator;
     100             :                         Func<IKernel, NinjectDependencyResolver> dependencyResolverCreator = container => new AkkaNinjectDependencyResolver(container, system);
     101             :                         if (originalDependencyResolverCreator == null)
     102             :                                 DependencyResolverCreator = dependencyResolverCreator;
     103             :                         else
     104             :                                 DependencyResolverCreator = container =>
     105             :                                 {
     106             :                                         originalDependencyResolverCreator(container);
     107             :                                         return dependencyResolverCreator(container);
     108             :                                 };
     109             : 
     110             :                         NinjectDependencyResolver.Start(kernel, prepareProvidedKernel);
     111             :                 }
     112             : 
     113             :                 /// <summary>
     114             :                 /// Calls <see cref="ActorSystem.Shutdown"/>
     115             :                 /// </summary>
     116           1 :                 public static void Stop()
     117             :                 {
     118             :                         var di = Current as AkkaNinjectDependencyResolver;
     119             :                         if (di != null)
     120             :                                 di.AkkaSystem.Shutdown();
     121             :                 }
     122             : 
     123             :                 #region Overrides of NinjectDependencyResolver
     124             : 
     125             :                 /// <summary>
     126             :                 /// Resolves instances of <paramref name="serviceType"/> using <see cref="Resolve(System.Type, Object)"/>.
     127             :                 /// </summary>
     128           1 :                 public override object Resolve(Type serviceType)
     129             :                 {
     130             :                         return Resolve(serviceType, null);
     131             :                 }
     132             : 
     133             :                 #endregion
     134             : 
     135             :                 #region Implementation of IAkkaAggregateResolver
     136             : 
     137             :                 /// <summary>
     138             :                 /// Resolves instances of <typeparamref name="TAggregate"/> using <see cref="AkkaResolve"/>.
     139             :                 /// </summary>
     140           1 :                 public virtual IActorRef ResolveActor<TAggregate, TAuthenticationToken>(Guid rsn)
     141             :                         where TAggregate : IAggregateRoot<TAuthenticationToken>
     142             :                 {
     143             :                         return (IActorRef)AkkaResolve(typeof(TAggregate), rsn, true);
     144             :                 }
     145             : 
     146             :                 /// <summary>
     147             :                 /// Resolves instances of <typeparamref name="T"/> using <see cref="AkkaResolve"/>.
     148             :                 /// </summary>
     149           1 :                 public IActorRef ResolveActor<T>()
     150             :                 {
     151             :                         return (IActorRef)AkkaResolve(typeof(T), null, true);
     152             :                 }
     153             : 
     154             :                 #endregion
     155             : 
     156             :                 #region Implementation of IAkkaSagaResolver
     157             : 
     158             :                 /// <summary>
     159             :                 /// Resolves instances of <typeparamref name="TSaga"/> using <see cref="ResolveSagaActor{TSaga,TAuthenticationToken}"/>.
     160             :                 /// </summary>
     161             :                 IActorRef IAkkaSagaResolver.ResolveActor<TSaga, TAuthenticationToken>(Guid rsn)
     162             :                 {
     163             :                         return ResolveSagaActor<TSaga, TAuthenticationToken>(rsn);
     164             :                 }
     165             : 
     166             :                 /// <summary>
     167             :                 /// Resolves instances of <typeparamref name="TSaga"/> using <see cref="AkkaResolve"/>.
     168             :                 /// </summary>
     169           1 :                 public virtual IActorRef ResolveSagaActor<TSaga, TAuthenticationToken>(Guid rsn)
     170             :                         where TSaga : ISaga<TAuthenticationToken>
     171             :                 {
     172             :                         return (IActorRef)AkkaResolve(typeof(TSaga), rsn, true);
     173             :                 }
     174             : 
     175             :                 #endregion
     176             : 
     177             :                 /// <summary>
     178             :                 /// Resolves instances of <paramref name="serviceType"/> using <see cref="IDependencyResolver.Resolve{T}"/>.
     179             :                 /// </summary>
     180           1 :                 protected virtual object RootResolve(Type serviceType)
     181             :                 {
     182             :                         return base.Resolve(serviceType);
     183             :                 }
     184             : 
     185             :                 /// <summary>
     186             :                 /// Resolves instances of <paramref name="serviceType"/> using <see cref="AkkaResolve"/>.
     187             :                 /// </summary>
     188           1 :                 public virtual object Resolve(Type serviceType, object rsn)
     189             :                 {
     190             :                         return AkkaResolve(serviceType, rsn);
     191             :                 }
     192             : 
     193             :                 /// <summary>
     194             :                 /// Resolves instances of <paramref name="serviceType"/> looking up <see cref="AkkaActors"/>, then <see cref="IDependencyResolver.Resolve{T}"/> and finally <see cref="AggregateFactory"/>.
     195             :                 /// </summary>
     196           1 :                 public virtual object AkkaResolve(Type serviceType, object rsn, bool isAForcedActorSearch = false)
     197             :                 {
     198             :                         IActorRef actorReference;
     199             :                         try
     200             :                         {
     201             :                                 if (AkkaActors.TryGetValue(serviceType, out actorReference))
     202             :                                         return actorReference;
     203             :                                 if (!isAForcedActorSearch)
     204             :                                         return base.Resolve(serviceType);
     205             :                         }
     206             :                         catch (ActivationException) { throw; }
     207             :                         catch ( /*ActorInitialization*/Exception) { /* */ }
     208             : 
     209             :                         Props properties;
     210             :                         Type typeToTest = serviceType;
     211             :                         while (typeToTest != null)
     212             :                         {
     213             :                                 Type[] types = typeToTest.GenericTypeArguments;
     214             :                                 if (types.Length == 1)
     215             :                                 {
     216             :                                         Type aggregateType = typeof (AkkaAggregateRoot<>).MakeGenericType(typeToTest.GenericTypeArguments.Single());
     217             :                                         if (typeToTest == aggregateType)
     218             :                                         {
     219             :                                                 typeToTest = aggregateType;
     220             :                                                 break;
     221             :                                         }
     222             :                                         Type sagaType = typeof (AkkaSaga<>).MakeGenericType(typeToTest.GenericTypeArguments.Single());
     223             :                                         if (typeToTest == sagaType)
     224             :                                         {
     225             :                                                 typeToTest = sagaType;
     226             :                                                 break;
     227             :                                         }
     228             :                                 }
     229             :                                 typeToTest = typeToTest.BaseType;
     230             :                         }
     231             : 
     232             :                         // This sorts out an out-of-order binder issue
     233             :                         if (AggregateFactory == null)
     234             :                                 AggregateFactory = Resolve<IAggregateFactory>();
     235             : 
     236             :                         if (typeToTest == null || !(typeToTest).IsAssignableFrom(serviceType))
     237             :                                 properties = Props.Create(() => (ActorBase)RootResolve(serviceType));
     238             :                         else
     239             :                                 properties = Props.Create(() => (ActorBase) AggregateFactory.Create(serviceType, rsn as Guid?, false));
     240             :                         string actorName = serviceType.FullName.Replace("`", string.Empty);
     241             :                         int index = actorName.IndexOf("[[", StringComparison.Ordinal);
     242             :                         if (index > -1)
     243             :                                 actorName = actorName.Substring(0, index);
     244             :                         actorReference = AkkaSystem.ActorOf(properties, string.Format("{0}~{1}", actorName, rsn));
     245             :                         AkkaActors.Add(serviceType, actorReference);
     246             :                         return actorReference;
     247             :                 }
     248             :         }
     249             : }

Generated by: LCOV version 1.10