Created
October 6, 2015 15:03
-
-
Save seesharper/ee6c8d3aca9d9723bda3 to your computer and use it in GitHub Desktop.
An AKKA dependency resolver
This file contains hidden or 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 System; | |
| using System.Collections.Concurrent; | |
| using System.Linq; | |
| using System.Runtime.CompilerServices; | |
| using Akka.Actor; | |
| using Akka.DI.Core; | |
| using LightInject; | |
| namespace LightInject.Akka | |
| { | |
| /// <summary> | |
| /// Provides services to the <see cref="Akka.Actor.ActorSystem "/> extension system | |
| /// used to create actors using the LightInject IoC container. | |
| /// </summary> | |
| public class LightInjectDependencyResolver : IDependencyResolver | |
| { | |
| private readonly IServiceContainer m_container; | |
| private readonly ConcurrentDictionary<string, Type> m_typeCache; | |
| private readonly ActorSystem m_system; | |
| private readonly ConditionalWeakTable<ActorBase, LightInject.Scope> m_references; | |
| /// <summary> | |
| /// Initializes a new instance of the <see cref="LightInjectDependencyResolver"/> class. | |
| /// </summary> | |
| /// <param name="container">The container used to resolve references</param> | |
| /// <param name="system">The actor system to plug into</param> | |
| /// <exception cref="ArgumentNullException"> | |
| /// Either the <paramref name="container"/> or the <paramref name="system"/> was null. | |
| /// </exception> | |
| public LightInjectDependencyResolver(IServiceContainer container, ActorSystem system) | |
| { | |
| if (system == null) throw new ArgumentNullException("system"); | |
| if (container == null) throw new ArgumentNullException("container"); | |
| this.m_container = container; | |
| m_typeCache = new ConcurrentDictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase); | |
| this.m_system = system; | |
| this.m_system.AddDependencyResolver(this); | |
| this.m_references = new ConditionalWeakTable<ActorBase, LightInject.Scope>(); | |
| } | |
| /// <summary> | |
| /// Retrieves an actor's type with the specified name | |
| /// </summary> | |
| /// <param name="actorName">The name of the actor to retrieve</param> | |
| /// <returns>The type with the specified actor name</returns> | |
| public Type GetType(string actorName) | |
| { | |
| m_typeCache.TryAdd(actorName, | |
| actorName.GetTypeValue() ?? | |
| m_container. | |
| AvailableServices. | |
| Where(registration => registration.ServiceName.Equals(actorName, StringComparison.InvariantCultureIgnoreCase)). | |
| Select(registration => registration.ImplementingType). | |
| FirstOrDefault()); | |
| return m_typeCache[actorName]; | |
| } | |
| /// <summary> | |
| /// Creates a delegate factory used to create actors based on their type | |
| /// </summary> | |
| /// <param name="actorType">The type of actor that the factory builds</param> | |
| /// <returns>A delegate factory used to create actors</returns> | |
| public Func<ActorBase> CreateActorFactory(Type actorType) | |
| { | |
| return () => | |
| { | |
| var scope = m_container.BeginScope(); | |
| var actor = (ActorBase)m_container.GetInstance(actorType); | |
| m_references.Add(actor, scope); | |
| return actor; | |
| }; | |
| } | |
| /// <summary> | |
| /// Used to register the configuration for an actor of the specified type <typeparam name="TActor"/> | |
| /// </summary> | |
| /// <typeparam name="TActor">The type of actor the configuration is based</typeparam> | |
| /// <returns>The configuration object for the given actor type</returns> | |
| public Props Create<TActor>() where TActor : ActorBase | |
| { | |
| return m_system.GetExtension<DIExt>().Props(typeof(TActor)); | |
| } | |
| /// <summary> | |
| /// Signals the DI container to release it's reference to the actor. | |
| /// <see href="http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501/ref=sr_1_1?ie=UTF8&qid=1425861096&sr=8-1&keywords=mark+seemann">HERE</see> | |
| /// </summary> | |
| /// <param name="actor">The actor to remove from the container</param> | |
| public void Release(ActorBase actor) | |
| { | |
| LightInject.Scope scope; | |
| if (m_references.TryGetValue(actor, out scope)) | |
| { | |
| scope.Dispose(); | |
| m_references.Remove(actor); | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment