diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs
index 02c72881c98..b9885c1290c 100644
--- a/src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs
+++ b/src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs
@@ -16,12 +16,16 @@ public class ActorPathBenchmarks
{
private ActorPath x;
private ActorPath y;
+ private ActorPath _childPath;
+ private Address _sysAdr = new Address("akka.tcp", "system", "127.0.0.1", 1337);
+ private Address _otherAdr = new Address("akka.tcp", "system", "127.0.0.1", 1338);
[GlobalSetup]
public void Setup()
{
- x = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "user");
- y = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "system");
+ x = new RootActorPath(_sysAdr, "user");
+ y = new RootActorPath(_sysAdr, "system");
+ _childPath = x / "parent" / "child";
}
[Benchmark]
@@ -45,7 +49,19 @@ public bool ActorPath_Equals()
[Benchmark]
public string ActorPath_ToString()
{
- return x.ToString();
+ return _childPath.ToString();
+ }
+
+ [Benchmark]
+ public string ActorPath_ToSerializationFormat()
+ {
+ return _childPath.ToSerializationFormat();
+ }
+
+ [Benchmark]
+ public string ActorPath_ToSerializationFormatWithAddress()
+ {
+ return _childPath.ToSerializationFormatWithAddress(_otherAdr);
}
}
}
diff --git a/src/benchmark/Akka.Benchmarks/Actor/NameAndUidBenchmarks.cs b/src/benchmark/Akka.Benchmarks/Actor/NameAndUidBenchmarks.cs
new file mode 100644
index 00000000000..c616f5527b4
--- /dev/null
+++ b/src/benchmark/Akka.Benchmarks/Actor/NameAndUidBenchmarks.cs
@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2021 Lightbend Inc.
+// Copyright (C) 2013-2021 .NET Foundation
+//
+//-----------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Akka.Actor;
+using Akka.Benchmarks.Configurations;
+using BenchmarkDotNet.Attributes;
+
+namespace Akka.Benchmarks.Actor
+{
+ [Config(typeof(MicroBenchmarkConfig))]
+ public class NameAndUidBenchmarks
+ {
+ public const string ActorPath = "foo#11241311";
+
+ [Benchmark]
+ public NameAndUid ActorCell_SplitNameAndUid()
+ {
+ return ActorCell.SplitNameAndUid(ActorPath);
+ }
+
+ [Benchmark]
+ public (string name, int uid) ActorCell_GetNameAndUid()
+ {
+ return ActorCell.GetNameAndUid(ActorPath);
+ }
+ }
+}
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ActorServiceProviderPropsWithScopesSpecs.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ActorServiceProviderPropsWithScopesSpecs.cs
index ef5d2fe0c39..4c2c84c5f54 100644
--- a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ActorServiceProviderPropsWithScopesSpecs.cs
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ActorServiceProviderPropsWithScopesSpecs.cs
@@ -21,7 +21,7 @@ namespace Akka.DependencyInjection.Tests
public class ActorServiceProviderPropsWithScopesSpecs : AkkaSpec, IClassFixture
{
- public ActorServiceProviderPropsWithScopesSpecs(AkkaDiFixture fixture, ITestOutputHelper output) : base(ServiceProviderSetup.Create(fixture.Provider)
+ public ActorServiceProviderPropsWithScopesSpecs(AkkaDiFixture fixture, ITestOutputHelper output) : base(DependencyResolverSetup.Create(fixture.Provider)
.And(BootstrapSetup.Create().WithConfig(TestKitBase.DefaultConfig)), output)
{
@@ -30,7 +30,7 @@ public ActorServiceProviderPropsWithScopesSpecs(AkkaDiFixture fixture, ITestOutp
[Fact(DisplayName = "DI: actors who receive an IServiceScope through Props should dispose of their dependencies upon termination")]
public void ActorsWithScopedDependenciesShouldDisposeUponStop()
{
- var spExtension = ServiceProvider.For(Sys);
+ var spExtension = DependencyResolver.For(Sys);
var props = spExtension.Props();
// create a scoped actor using the props from Akka.DependencyInjection
@@ -60,11 +60,23 @@ public void ActorsWithScopedDependenciesShouldDisposeUponStop()
deps2.Dependencies.All(x => x.Disposed).Should().BeFalse();
}
+ [Fact(DisplayName = "DI: should be able to start actors with untyped Props")]
+ public void ShouldStartActorWithUntypedProps()
+ {
+ var spExtension = DependencyResolver.For(Sys);
+ var props = spExtension.Props(typeof(ScopedActor));
+
+ // create a scoped actor using the props from Akka.DependencyInjection
+ var scoped1 = Sys.ActorOf(props, "scoped1");
+ scoped1.Tell(new FetchDependencies());
+ var deps1 = ExpectMsg();
+ }
+
[Fact(DisplayName =
"DI: actors who receive an IServiceScope through Props should dispose of their dependencies and recreate upon restart")]
public void ActorsWithScopedDependenciesShouldDisposeAndRecreateUponRestart()
{
- var spExtension = ServiceProvider.For(Sys);
+ var spExtension = DependencyResolver.For(Sys);
var props = spExtension.Props();
// create a scoped actor using the props from Akka.DependencyInjection
@@ -95,7 +107,7 @@ public void ActorsWithScopedDependenciesShouldDisposeAndRecreateUponRestart()
"DI: actors who receive a mix of dependencies via IServiceScope should dispose ONLY of their scoped dependencies and recreate upon restart")]
public void ActorsWithMixedDependenciesShouldDisposeAndRecreateScopedUponRestart()
{
- var spExtension = ServiceProvider.For(Sys);
+ var spExtension = DependencyResolver.For(Sys);
var props = spExtension.Props();
// create a scoped actor using the props from Akka.DependencyInjection
@@ -134,7 +146,7 @@ public void ActorsWithMixedDependenciesShouldDisposeAndRecreateScopedUponRestart
public void ActorsWithNonDiDependenciesShouldStart()
{
//
- var spExtension = ServiceProvider.For(Sys);
+ var spExtension = DependencyResolver.For(Sys);
var arg1 = "foo";
var arg2 = "bar";
var props = spExtension.Props(arg1, arg2);
@@ -182,7 +194,7 @@ public void ActorsWithNonDiDependenciesShouldStart()
public void ServiceProvider_Props_should_support_copying()
{
//
- var spExtension = ServiceProvider.For(Sys);
+ var spExtension = DependencyResolver.For(Sys);
var arg1 = "foo";
var arg2 = "bar";
var props = spExtension.Props(arg1, arg2).WithRouter(new RoundRobinPool(10).WithSupervisorStrategy(new OneForOneStrategy(
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/DelegateInjectionSpecs.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/DelegateInjectionSpecs.cs
index bc0a64388ad..1e2342644d6 100644
--- a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/DelegateInjectionSpecs.cs
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/DelegateInjectionSpecs.cs
@@ -1,4 +1,10 @@
-using System;
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2021 Lightbend Inc.
+// Copyright (C) 2013-2021 .NET Foundation
+//
+//-----------------------------------------------------------------------
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -73,7 +79,7 @@ public async Task DI_should_be_able_to_retrieve_singleton_using_delegate_from_in
internal class ParentActor : UntypedActor
{
public static Props Props(ActorSystem system) =>
- ServiceProvider.For(system).Props();
+ DependencyResolver.For(system).Props();
private readonly IActorRef _echoActor;
@@ -114,7 +120,7 @@ public AkkaService(IServiceProvider serviceProvider)
public Task StartAsync(CancellationToken cancellationToken)
{
- var setup = ServiceProviderSetup.Create(_serviceProvider)
+ var setup = DependencyResolverSetup.Create(_serviceProvider)
.And(BootstrapSetup.Create().WithConfig(TestKitBase.DefaultConfig));
ActorSystem = ActorSystem.Create("TestSystem", setup);
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ServiceProviderSetupSpecs.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ServiceProviderSetupSpecs.cs
index e14e8e8ee4b..d44085f69f6 100644
--- a/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ServiceProviderSetupSpecs.cs
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection.Tests/ServiceProviderSetupSpecs.cs
@@ -18,7 +18,7 @@ namespace Akka.DependencyInjection.Tests
{
public class ServiceProviderSetupSpecs : AkkaSpec, IClassFixture
{
- public ServiceProviderSetupSpecs(AkkaDiFixture fixture, ITestOutputHelper output) : base(ServiceProviderSetup.Create(fixture.Provider)
+ public ServiceProviderSetupSpecs(AkkaDiFixture fixture, ITestOutputHelper output) : base(DependencyResolverSetup.Create(fixture.Provider)
.And(BootstrapSetup.Create().WithConfig(TestKitBase.DefaultConfig)), output)
{
@@ -27,29 +27,29 @@ public ServiceProviderSetupSpecs(AkkaDiFixture fixture, ITestOutputHelper output
[Fact(DisplayName = "DI: Should access Microsoft.Extensions.DependencyInjection.IServiceProvider from ServiceProvider ActorSystem extension")]
public void ShouldAccessServiceProviderFromActorSystemExtension()
{
- var sp = ServiceProvider.For(Sys);
- var dep = sp.Provider.GetService();
+ var sp = DependencyResolver.For(Sys);
+ var dep = sp.Resolver.GetService();
dep.Should().BeOfType();
- var dep2 = sp.Provider.GetService();
+ var dep2 = sp.Resolver.GetService();
dep2.Should().NotBe(dep); // the two transient instances should be different
// scoped services should be the same
- var scoped1 = sp.Provider.GetService();
- var scoped2 = sp.Provider.GetService();
+ var scoped1 = sp.Resolver.GetService();
+ var scoped2 = sp.Resolver.GetService();
scoped1.Should().Be(scoped2);
// create a new scope
- using (var newScope = sp.Provider.CreateScope())
+ using (var newScope = sp.Resolver.CreateScope())
{
- var scoped3 = newScope.ServiceProvider.GetService();
+ var scoped3 = newScope.Resolver.GetService();
scoped1.Should().NotBe(scoped3);
}
// singleton services should be the same
- var singleton1 = sp.Provider.GetService();
- var singleton2 = sp.Provider.GetService();
+ var singleton1 = sp.Resolver.GetService();
+ var singleton2 = sp.Resolver.GetService();
singleton1.Should().Be(singleton2);
}
@@ -67,7 +67,7 @@ public void ShouldAccessServiceProviderFromActorSystemExtension()
{
Action getSp = () =>
{
- var sp = ServiceProvider.For(Sys);
+ var sp = DependencyResolver.For(Sys);
};
getSp.Should().Throw();
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolver.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolver.cs
new file mode 100644
index 00000000000..4917a1b8ed5
--- /dev/null
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolver.cs
@@ -0,0 +1,125 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2021 Lightbend Inc.
+// Copyright (C) 2013-2021 .NET Foundation
+//
+//-----------------------------------------------------------------------
+
+using System;
+using Akka.Actor;
+using Akka.Configuration;
+using Akka.Event;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Akka.DependencyInjection
+{
+ ///
+ /// Provides users with immediate access to the bound to
+ /// this , if any.
+ ///
+ public sealed class DependencyResolver : IExtension
+ {
+ public DependencyResolver(IDependencyResolver resolver)
+ {
+ Resolver = resolver;
+ }
+
+ ///
+ /// The globally scoped .
+ ///
+ ///
+ /// Per https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines - please use
+ /// the appropriate for your actors and the dependencies they consume. DI is typically
+ /// not used for long-lived, stateful objects such as actors.
+ ///
+ /// Therefore, injecting transient dependencies via constructors is a bad idea in most cases. You'd be far better off
+ /// creating a local "request scope" each time your actor processes a message that depends on a transient dependency,
+ /// such as a database connection, and disposing that scope once the operation is complete.
+ ///
+ /// Actors are not MVC Controllers. Actors can live forever, have the ability to restart, and are often stateful.
+ /// Be mindful of this as you use this feature or bad things will happen. Akka.NET does not magically manage scopes
+ /// for you.
+ ///
+ public IDependencyResolver Resolver { get; }
+
+ public static DependencyResolver For(ActorSystem actorSystem)
+ {
+ return actorSystem.WithExtension();
+ }
+
+ ///
+ /// Uses a delegate to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// Optional. Any constructor arguments that will be passed into the actor's constructor directly without being resolved by DI first.
+ /// A new instance which uses DI internally.
+ public Props Props(params object[] args) where T : ActorBase
+ {
+ return Resolver.Props(args);
+ }
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// A new instance which uses DI internally.
+ public Props Props() where T : ActorBase
+ {
+ return Resolver.Props();
+ }
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// A new instance which uses DI internally.
+ public Props Props(Type type)
+ {
+ return Resolver.Props(type);
+ }
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// Optional. Any constructor arguments that will be passed into the actor's constructor directly without being resolved by DI first.
+ /// A new instance which uses DI internally.
+ public Props Props(Type type, params object[] args)
+ {
+ return Resolver.Props(type, args);
+ }
+ }
+
+ ///
+ /// INTERNAL API
+ ///
+ public sealed class DependencyResolverExtension : ExtensionIdProvider
+ {
+ public override DependencyResolver CreateExtension(ExtendedActorSystem system)
+ {
+ var setup = system.Settings.Setup.Get();
+ if (setup.HasValue) return new DependencyResolver(setup.Value.DependencyResolver);
+
+ var exception = new ConfigurationException("Unable to find [DependencyResolverSetup] included in ActorSystem settings." +
+ " Please specify one before attempting to use dependency injection inside Akka.NET.");
+ system.EventStream.Publish(new Error(exception, "Akka.DependencyInjection", typeof(DependencyResolverExtension), exception.Message));
+ throw exception;
+ }
+ }
+}
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolverSetup.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolverSetup.cs
new file mode 100644
index 00000000000..3df580095a3
--- /dev/null
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection/DependencyResolverSetup.cs
@@ -0,0 +1,84 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2021 Lightbend Inc.
+// Copyright (C) 2013-2021 .NET Foundation
+//
+//-----------------------------------------------------------------------
+
+using System;
+using Akka.Actor;
+using Akka.Actor.Setup;
+
+namespace Akka.DependencyInjection
+{
+ ///
+ /// Used to help bootstrap an with dependency injection (DI)
+ /// support via a reference.
+ ///
+ /// The will be used to access previously registered services
+ /// in the creation of actors and other pieces of infrastructure inside Akka.NET.
+ ///
+ /// The constructor is internal. Please use to create a new instance.
+ ///
+ [Obsolete("Used DependencyResolverSetup instead.")]
+ public class ServiceProviderSetup : Setup
+ {
+ internal ServiceProviderSetup(IServiceProvider serviceProvider)
+ {
+ ServiceProvider = serviceProvider;
+ }
+
+ public IServiceProvider ServiceProvider { get; }
+
+ public static ServiceProviderSetup Create(IServiceProvider provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ return new ServiceProviderSetup(provider);
+ }
+ }
+
+ ///
+ /// Used to help bootstrap an with dependency injection (DI)
+ /// support via a reference.
+ ///
+ /// The will be used to access previously registered services
+ /// in the creation of actors and other pieces of infrastructure inside Akka.NET.
+ ///
+ /// The constructor is internal. Please use to create a new instance.
+ ///
+ public class DependencyResolverSetup : Setup
+ {
+ public IDependencyResolver DependencyResolver { get; }
+
+ internal DependencyResolverSetup(IDependencyResolver dependencyResolver)
+ {
+ DependencyResolver = dependencyResolver;
+ }
+
+ ///
+ /// Creates a new instance of DependencyResolverSetup, passing in
+ /// here creates an that resolves dependencies from the specified
+ ///
+ public static DependencyResolverSetup Create(IServiceProvider provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ return new DependencyResolverSetup(new ServiceProviderDependencyResolver(provider));
+ }
+
+ ///
+ /// Creates a new instance of DependencyResolverSetup, an implementation of
+ /// can be passed in here to resolve services from test or alternative DI frameworks.
+ ///
+ public static DependencyResolverSetup Create(IDependencyResolver provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ return new DependencyResolverSetup(provider);
+ }
+ }
+}
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection/IDependencyResolver.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection/IDependencyResolver.cs
new file mode 100644
index 00000000000..d221f6480db
--- /dev/null
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection/IDependencyResolver.cs
@@ -0,0 +1,61 @@
+// //-----------------------------------------------------------------------
+// //
+// // Copyright (C) 2009-2021 Lightbend Inc.
+// // Copyright (C) 2013-2021 .NET Foundation
+// //
+// //-----------------------------------------------------------------------
+
+using System;
+using Akka.Actor;
+
+namespace Akka.DependencyInjection
+{
+ ///
+ /// Interface abstraction for working with DI providers
+ /// in Akka.NET without being bound to any specific implementation.
+ ///
+ ///
+ /// See for a reference implementation.
+ ///
+ public interface IDependencyResolver
+ {
+ IResolverScope CreateScope();
+ object GetService();
+ object GetService(Type type);
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// Optional. Any constructor arguments that will be passed into the actor's constructor directly without being resolved by DI first.
+ /// A new instance which uses DI internally.
+ Props Props(Type type, params object[] args);
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// A new instance which uses DI internally.
+ Props Props(Type type);
+
+ ///
+ /// Used to dynamically instantiate an actor where some of the constructor arguments are populated via dependency injection
+ /// and others are not.
+ ///
+ ///
+ /// YOU ARE RESPONSIBLE FOR MANAGING THE LIFECYCLE OF YOUR OWN DEPENDENCIES. AKKA.NET WILL NOT ATTEMPT TO DO IT FOR YOU.
+ ///
+ /// The type of actor to instantiate.
+ /// Optional. Any constructor arguments that will be passed into the actor's constructor directly without being resolved by DI first.
+ /// A new instance which uses DI internally.
+ Props Props(params object[] args) where T : ActorBase;
+ }
+}
\ No newline at end of file
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProvider.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProvider.cs
index 883730d0b27..aa652707737 100644
--- a/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProvider.cs
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProvider.cs
@@ -17,6 +17,10 @@ namespace Akka.DependencyInjection
/// Provides users with immediate access to the bound to
/// this , if any.
///
+ ///
+ /// [OBSOLETE] Switch to the instead.
+ ///
+ [Obsolete("Replaced by the Akka.DependencyInjection.DependencyResolver in Akka.NET v1.4.20. Please switch to that.")]
public sealed class ServiceProvider : IExtension
{
public ServiceProvider(IServiceProvider provider)
@@ -66,6 +70,7 @@ public static ServiceProvider For(ActorSystem actorSystem)
///
/// INTERNAL API
///
+ [Obsolete("Use the DependencyResolverExtensions instead.")]
public sealed class ServiceProviderExtension : ExtensionIdProvider
{
public override ServiceProvider CreateExtension(ExtendedActorSystem system)
@@ -88,17 +93,16 @@ public override ServiceProvider CreateExtension(ExtendedActorSystem system)
///
/// Used to create actors via the .
///
- /// the actor type
- internal sealed class ServiceProviderActorProducer : IIndirectActorProducer where TActor:ActorBase
+ internal class ServiceProviderActorProducer : IIndirectActorProducer
{
private readonly IServiceProvider _provider;
private readonly object[] _args;
- public ServiceProviderActorProducer(IServiceProvider provider, object[] args)
+ public ServiceProviderActorProducer(IServiceProvider provider, Type actorType, object[] args)
{
_provider = provider;
_args = args;
- ActorType = typeof(TActor);
+ ActorType = actorType;
}
public ActorBase Produce()
@@ -113,4 +117,19 @@ public void Release(ActorBase actor)
// no-op
}
}
+
+ ///
+ /// INTERNAL API
+ ///
+ /// Used to create actors via the .
+ ///
+ /// the actor type
+ internal class ServiceProviderActorProducer : ServiceProviderActorProducer where TActor:ActorBase
+ {
+
+ public ServiceProviderActorProducer(IServiceProvider provider, object[] args)
+ : base(provider, typeof(TActor), args)
+ {
+ }
+ }
}
diff --git a/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProviderDependencyResolver.cs b/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProviderDependencyResolver.cs
new file mode 100644
index 00000000000..8fdab7c3ada
--- /dev/null
+++ b/src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProviderDependencyResolver.cs
@@ -0,0 +1,62 @@
+// //-----------------------------------------------------------------------
+// //
+// // Copyright (C) 2009-2021 Lightbend Inc.
+// // Copyright (C) 2013-2021 .NET Foundation
+// //
+// //-----------------------------------------------------------------------
+
+using System;
+using Akka.Actor;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Akka.DependencyInjection
+{
+ ///
+ /// INTERNAL API.
+ ///
+ /// implementation backed by
+ ///
+ public class ServiceProviderDependencyResolver : IDependencyResolver
+ {
+ public IServiceProvider ServiceProvider { get; }
+
+ public ServiceProviderDependencyResolver(IServiceProvider serviceProvider)
+ {
+ ServiceProvider = serviceProvider;
+ }
+
+ public IResolverScope CreateScope()
+ {
+ return new ServiceProviderScope(ServiceProvider.CreateScope());
+ }
+
+ public object GetService()
+ {
+ return ServiceProvider.GetService();
+ }
+
+ public object GetService(Type type)
+ {
+ return ServiceProvider.GetService(type);
+ }
+
+ public Props Props(Type type, params object[] args)
+ {
+ if(typeof(ActorBase).IsAssignableFrom(type))
+ return Akka.Actor.Props.CreateBy(new ServiceProviderActorProducer(ServiceProvider, type, args));
+ throw new ArgumentException(nameof(type), $"[{type}] does not implement Akka.Actor.ActorBase.");
+ }
+
+ public Props Props(Type type)
+ {
+ return Props(type, Array.Empty