Skip to content

Instantly share code, notes, and snippets.

@BlueManiac
Created December 18, 2017 16:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BlueManiac/a688439b096b6d5b7c37b93c16ea3774 to your computer and use it in GitHub Desktop.
Save BlueManiac/a688439b096b6d5b7c37b93c16ea3774 to your computer and use it in GitHub Desktop.
Akka.NET DI with .net Core DI
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace Common.Akka.DependencyInjection
{
public class ActorScope : IServiceScope
{
public ActorScope(IServiceProvider provider)
{
ServiceProvider = provider;
}
public void Dispose()
{
}
public IServiceProvider ServiceProvider { get; }
}
}
using System;
using Microsoft.Extensions.DependencyInjection;
namespace Common.Akka.DependencyInjection
{
public class ActorScopeFactory : IServiceScopeFactory
{
private readonly IServiceProvider _provider;
public ActorScopeFactory(IServiceProvider provider)
{
_provider = provider;
}
public IServiceScope CreateScope()
{
return new ActorScope(_provider);
}
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.DI.Core;
using Microsoft.Extensions.DependencyInjection;
namespace Common.Akka.DependencyInjection
{
public class ServiceProviderResolver : IDependencyResolver
{
private readonly IServiceProvider _provider;
private readonly ActorSystem _actorSystem;
private readonly string _reference;
private readonly ConcurrentDictionary<string, Type> _typeCache;
private readonly ConditionalWeakTable<ActorBase, IServiceScope> _references;
private readonly ActorScopeFactory _scopeFactory;
public ServiceProviderResolver(IServiceProvider provider, ActorSystem actorSystem, string reference = null)
{
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
_actorSystem = actorSystem ?? throw new ArgumentNullException(nameof(actorSystem));
_reference = reference ?? _actorSystem.Name;
_actorSystem.AddDependencyResolver(this);
_typeCache = new ConcurrentDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
_references = new ConditionalWeakTable<ActorBase, IServiceScope>();
_scopeFactory = new ActorScopeFactory(provider);
}
public Type GetType(string actorName)
{
return _typeCache.GetOrAdd(actorName, actorName.GetTypeValue());
}
public Func<ActorBase> CreateActorFactory(Type actorType)
{
return () =>
{
var scope = _scopeFactory.CreateScope();
try
{
if (!(_provider.GetService(actorType) is ActorBase actor))
{
throw new ArgumentException($"Actor of type {actorType} has not been registered in the ConfigureServices method in the startup class. (in {_reference})");
}
_references.Add(actor, scope);
return actor;
}
catch (InvalidOperationException ex)
{
throw new InvalidOperationException($"Could not resolve service in {_reference}. Is all services registered in the ConfigureServices method in the startup class?", ex);
}
};
}
public Props Create<TActor>() where TActor : ActorBase
{
return Create(typeof(TActor));
}
public Props Create(Type actorType)
{
return _actorSystem.GetExtension<DIExt>().Props(actorType);
}
public void Release(ActorBase actor)
{
if (_references.TryGetValue(actor, out var scope))
{
scope.Dispose();
_references.Remove(actor);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment