Skip to content

Commit 8a370d7

Browse files
committed
First pass at getting rid of expressions
I have a feeling that CreateProducer might still be needed but testing this out for now.
1 parent c60c702 commit 8a370d7

File tree

2 files changed

+25
-70
lines changed

2 files changed

+25
-70
lines changed

src/core/Akka.TestKit/TestKitBase_ActorOf.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//-----------------------------------------------------------------------
77

88
using System;
9-
using System.Linq.Expressions;
109
using Akka.Actor;
1110
using Akka.Actor.Dsl;
1211

@@ -71,7 +70,7 @@ public IActorRef ActorOf(Props props, string name)
7170
/// <typeparam name="TActor">The type of the actor.</typeparam>
7271
/// <param name="factory">An expression that calls the constructor of <typeparamref name="TActor"/></param>
7372
/// <returns>TBD</returns>
74-
public IActorRef ActorOf<TActor>(Expression<Func<TActor>> factory) where TActor : ActorBase
73+
public IActorRef ActorOf<TActor>(Func<TActor> factory) where TActor : ActorBase
7574
{
7675
return Sys.ActorOf(Props.Create(factory), null);
7776
}
@@ -87,7 +86,7 @@ public IActorRef ActorOf<TActor>(Expression<Func<TActor>> factory) where TActor
8786
/// <param name="factory">An expression that calls the constructor of <typeparamref name="TActor"/></param>
8887
/// <param name="name">The name of the actor.</param>
8988
/// <returns>TBD</returns>
90-
public IActorRef ActorOf<TActor>(Expression<Func<TActor>> factory, string name) where TActor : ActorBase
89+
public IActorRef ActorOf<TActor>(Func<TActor> factory, string name) where TActor : ActorBase
9190
{
9291
return Sys.ActorOf(Props.Create(factory), name);
9392
}
@@ -201,7 +200,7 @@ public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Props props, string na
201200
/// <param name="supervisor">The supervisor</param>
202201
/// <param name="name">Optional: The name.</param>
203202
/// <returns>TBD</returns>
204-
public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Expression<Func<TActor>> factory, IActorRef supervisor, string name = null) where TActor : ActorBase
203+
public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Func<TActor> factory, IActorRef supervisor, string name = null) where TActor : ActorBase
205204
{
206205
return new TestActorRef<TActor>(Sys, Props.Create(factory), supervisor, name);
207206
}
@@ -218,7 +217,7 @@ public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Expression<Func<TActor
218217
/// <param name="factory">An expression that calls the constructor of <typeparamref name="TActor"/></param>
219218
/// <param name="name">Optional: The name.</param>
220219
/// <returns>TBD</returns>
221-
public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Expression<Func<TActor>> factory, string name = null) where TActor : ActorBase
220+
public TestActorRef<TActor> ActorOfAsTestActorRef<TActor>(Func<TActor> factory, string name = null) where TActor : ActorBase
222221
{
223222
return new TestActorRef<TActor>(Sys, Props.Create(factory), NoSupervisor, name);
224223
}
@@ -333,7 +332,7 @@ public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TStat
333332
/// <param name="name">Optional: The name.</param>
334333
/// <param name="withLogging">Optional: If set to <c>true</c> logs state changes of the FSM as Debug messages. Default is <c>false</c>.</param>
335334
/// <returns>TBD</returns>
336-
public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TState, TData>(Expression<Func<TFsmActor>> factory, IActorRef supervisor, string name = null, bool withLogging = false)
335+
public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TState, TData>(Func<TFsmActor> factory, IActorRef supervisor, string name = null, bool withLogging = false)
337336
where TFsmActor : FSM<TState, TData>
338337
{
339338
return new TestFSMRef<TFsmActor, TState, TData>(Sys, Props.Create(factory), supervisor, name, withLogging);
@@ -351,7 +350,7 @@ public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TStat
351350
/// <param name="name">Optional: The name.</param>
352351
/// <param name="withLogging">Optional: If set to <c>true</c> logs state changes of the FSM as Debug messages. Default is <c>false</c>.</param>
353352
/// <returns>TBD</returns>
354-
public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TState, TData>(Expression<Func<TFsmActor>> factory, string name = null, bool withLogging = false)
353+
public TestFSMRef<TFsmActor, TState, TData> ActorOfAsTestFSMRef<TFsmActor, TState, TData>(Func<TFsmActor> factory, string name = null, bool withLogging = false)
355354
where TFsmActor : FSM<TState, TData>
356355
{
357356
return new TestFSMRef<TFsmActor, TState, TData>(Sys, Props.Create(factory), NoSupervisor, name, withLogging);

src/core/Akka/Actor/Props.cs

Lines changed: 19 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//-----------------------------------------------------------------------
1+
//-----------------------------------------------------------------------
22
// <copyright file="Props.cs" company="Akka.NET Project">
33
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
44
// Copyright (C) 2013-2025 .NET Foundation <https://github.com/akkadotnet/akka.net>
@@ -8,13 +8,9 @@
88
using System;
99
using System.Collections.Generic;
1010
using System.Linq;
11-
using System.Linq.Expressions;
12-
using Akka.Configuration;
1311
using Akka.Dispatch;
1412
using Akka.Routing;
1513
using Akka.Util;
16-
using Akka.Util.Internal;
17-
using Akka.Util.Reflection;
1814
using Newtonsoft.Json;
1915

2016
namespace Akka.Actor
@@ -46,8 +42,6 @@ public class Props : IEquatable<Props>, ISurrogated
4642
/// </note>
4743
/// </summary>
4844
public static readonly Props None = null;
49-
private Type _inputType;
50-
private Type _outputType;
5145
private readonly IIndirectActorProducer _producer;
5246

5347
/// <summary>
@@ -163,13 +157,12 @@ public Props(Deploy deploy, Type type, IEnumerable<object> args)
163157
/// <param name="args">The arguments needed to create the actor.</param>
164158
/// <exception cref="ArgumentException">This exception is thrown if <paramref name="type" /> is an unknown actor producer.</exception>
165159
public Props(Deploy deploy, Type type, params object[] args)
166-
#pragma warning disable CS0618 // Type or member is obsolete
167-
: this(CreateProducer(type, args), deploy, args) // have to preserve the "CreateProducer" call here to preserve backwards compat with Akka.DI.Core
168-
#pragma warning restore CS0618 // Type or member is obsolete
160+
: this(new ActivatorProducer(type, args), deploy, args)
169161
{
170162

171163
}
172164

165+
173166
/// <summary>
174167
/// Initializes a new instance of the <see cref="Props" /> class using a specified <see cref="IIndirectActorProducer"/>.
175168
/// </summary>
@@ -182,7 +175,6 @@ public Props(Deploy deploy, Type type, params object[] args)
182175
internal Props(IIndirectActorProducer producer, Deploy deploy, params object[] args)
183176
{
184177
Deploy = deploy;
185-
_inputType = producer.ActorType;
186178
Arguments = args ?? NoArgs;
187179
_producer = producer;
188180
}
@@ -195,9 +187,7 @@ public Type Type
195187
{
196188
get
197189
{
198-
if (_outputType == null) _outputType = _producer.ActorType;
199-
200-
return _outputType;
190+
return _producer.ActorType;
201191
}
202192
}
203193

@@ -225,9 +215,8 @@ public string Dispatcher
225215
/// </summary>
226216
public string TypeName
227217
{
228-
get => _inputType.AssemblyQualifiedName;
229-
//for serialization
230-
private set => _inputType = Type.GetType(value);
218+
get => _producer.ActorType.AssemblyQualifiedName;
219+
//private set => _producer.ActorType = Type.GetType(value);
231220
}
232221

233222
/// <summary>
@@ -283,7 +272,7 @@ public ISurrogate ToSurrogate(ActorSystem system)
283272

284273
private bool CompareInputType(Props other)
285274
{
286-
return _inputType == other._inputType;
275+
return _producer.ActorType == other._producer.ActorType;
287276
}
288277

289278
private bool CompareDeploy(Props other)
@@ -328,15 +317,14 @@ public override bool Equals(object obj)
328317
return Equals((Props)obj);
329318
}
330319

331-
332320
public override int GetHashCode()
333321
{
334322
unchecked
335323
{
336324
var hashCode = Deploy != null ? Deploy.GetHashCode() : 0;
337325
// hashCode = (hashCode*397) ^ (SupervisorStrategy != null ? SupervisorStrategy.GetHashCode() : 0);
338326
// hashCode = (hashCode*397) ^ (Arguments != null ? Arguments.GetHashCode() : 0);
339-
hashCode = (hashCode * 397) ^ (_inputType != null ? _inputType.GetHashCode() : 0);
327+
hashCode = (hashCode * 397) ^ (_producer.ActorType != null ? _producer.ActorType.GetHashCode() : 0);
340328
return hashCode;
341329
}
342330
}
@@ -349,19 +337,9 @@ public override int GetHashCode()
349337
/// <param name="supervisorStrategy">Optional: The supervisor strategy used to manage the actor.</param>
350338
/// <returns>The newly created <see cref="Akka.Actor.Props" />.</returns>
351339
/// <exception cref="ArgumentException">The create function must be a 'new T (args)' expression</exception>
352-
public static Props Create<TActor>(Expression<Func<TActor>> factory,
353-
SupervisorStrategy supervisorStrategy = null) where TActor : ActorBase
340+
public static Props Create<TActor>(Func<TActor> factory, SupervisorStrategy supervisorStrategy = null) where TActor : ActorBase
354341
{
355-
if (factory.Body is UnaryExpression)
356-
return new DynamicProps<TActor>(factory.Compile());
357-
358-
var newExpression = factory.Body.AsInstanceOf<NewExpression>();
359-
if (newExpression == null)
360-
throw new ArgumentException("The create function must be a 'new T (args)' expression");
361-
362-
var args = newExpression.Arguments.Count > 0 ? newExpression.GetArguments() : NoArgs;
363-
364-
return new Props(new ActivatorProducer(typeof(TActor), args), DefaultDeploy, args){ SupervisorStrategy = supervisorStrategy };
342+
return new Props(new FactoryProducer<TActor>(factory), DefaultDeploy, NoArgs) { SupervisorStrategy = supervisorStrategy };
365343
}
366344

367345
/// <summary>
@@ -406,7 +384,7 @@ public static Props CreateBy(IIndirectActorProducer producer, params object[] ar
406384
/// <returns>The newly created <see cref="Akka.Actor.Props" />.</returns>
407385
public static Props Create<TActor>(SupervisorStrategy supervisorStrategy) where TActor : ActorBase, new()
408386
{
409-
return new Props(new ActivatorProducer(typeof(TActor), NoArgs), DefaultDeploy, NoArgs){ SupervisorStrategy = supervisorStrategy };
387+
return new Props(new FactoryProducer<TActor>(() => new TActor()), DefaultDeploy, NoArgs) { SupervisorStrategy = supervisorStrategy };
410388
}
411389

412390
/// <summary>
@@ -468,7 +446,7 @@ public Props WithRouter(RouterConfig routerConfig)
468446
copy.Deploy = Deploy.WithRouterConfig(routerConfig);
469447
return copy;
470448
}
471-
449+
472450
/// <summary>
473451
/// Creates a new <see cref="Akka.Actor.Props" /> with a given stash size.
474452
/// <note>
@@ -499,12 +477,13 @@ public Props WithStashCapacity(int stashCapacity)
499477
public Props WithDeploy(Deploy deploy)
500478
{
501479
var copy = Copy();
502-
var original = copy.Deploy;
480+
//var original = copy.Deploy;
503481

504482
// TODO: this is a hack designed to preserve explicit router deployments https://github.com/akkadotnet/akka.net/issues/546
505483
// in reality, we should be able to do copy.Deploy = deploy.WithFallback(copy.Deploy); but that blows up at the moment
506484
// - Aaron Stannard
507485
copy.Deploy = deploy.WithFallback(copy.Deploy);
486+
508487
//if (!(original.RouterConfig is NoRouter || original.RouterConfig is FromConfig) && deploy.RouterConfig is NoRouter)
509488
//{
510489
// copy.Deploy = deploy.WithFallback(copy.Deploy);
@@ -555,17 +534,13 @@ public Props WithSupervisorStrategy(SupervisorStrategy supervisorStrategy)
555534
/// <returns>The newly created actor</returns>
556535
public virtual ActorBase NewActor()
557536
{
558-
var type = Type;
559-
var arguments = Arguments;
560537
try
561538
{
562539
return _producer.Produce();
563540
}
564541
catch (Exception e)
565542
{
566-
throw new TypeLoadException(
567-
$"Error while creating actor instance of type {type} with {arguments.Length} args: ({StringFormat.SafeJoin(",", arguments)})",
568-
e);
543+
throw new TypeLoadException($"Error while creating actor instance of type {Type} with {Arguments.Length} args: ({StringFormat.SafeJoin(",", Arguments)})", e);
569544
}
570545
}
571546

@@ -578,23 +553,6 @@ protected virtual Props Copy()
578553
return new Props(_producer, Deploy, Arguments) { SupervisorStrategy = SupervisorStrategy };
579554
}
580555

581-
[Obsolete("we should not be calling this method. Pass in an explicit IIndirectActorProducer reference instead.")]
582-
private static IIndirectActorProducer CreateProducer(Type type, object[] args)
583-
{
584-
if (type == null) return DefaultProducer.Instance;
585-
586-
if (typeof(IIndirectActorProducer).IsAssignableFrom(type))
587-
return Activator.CreateInstance(type, args).AsInstanceOf<IIndirectActorProducer>();
588-
589-
if (typeof(ActorBase).IsAssignableFrom(type)) return new ActivatorProducer(type, args);
590-
591-
throw new ArgumentException($"Unknown actor producer [{type.FullName}]", nameof(type));
592-
}
593-
594-
/// <summary>
595-
/// Signals the producer that it can release its reference to the actor.
596-
/// </summary>
597-
/// <param name="actor">The actor to release</param>
598556
internal void Release(ActorBase actor)
599557
{
600558
try
@@ -687,23 +645,22 @@ public ActivatorProducer(Type actorType, object[] args)
687645

688646
public ActorBase Produce()
689647
{
690-
return Activator.CreateInstance(ActorType, _args).AsInstanceOf<ActorBase>();
648+
return (ActorBase)Activator.CreateInstance(ActorType, _args);
691649
}
692650

693651
public Type ActorType { get; }
694652

695-
696653
public void Release(ActorBase actor)
697654
{
698655
actor = null;
699656
}
700657
}
701658

702-
private class FactoryConsumer<TActor> : IIndirectActorProducer where TActor : ActorBase
659+
private class FactoryProducer<TActor> : IIndirectActorProducer where TActor : ActorBase
703660
{
704661
private readonly Func<TActor> _factory;
705662

706-
public FactoryConsumer(Func<TActor> factory)
663+
public FactoryProducer(Func<TActor> factory)
707664
{
708665
_factory = factory;
709666
}
@@ -715,7 +672,6 @@ public ActorBase Produce()
715672

716673
public Type ActorType => typeof(TActor);
717674

718-
719675
public void Release(ActorBase actor)
720676
{
721677
actor = null;
@@ -828,4 +784,4 @@ public interface IIndirectActorProducer
828784
/// <param name="actor">The actor to release</param>
829785
void Release(ActorBase actor);
830786
}
831-
}
787+
}

0 commit comments

Comments
 (0)