Last active
March 29, 2022 09:38
-
-
Save Horusiath/f5c77e043ee17e02d0311315bcde9c79 to your computer and use it in GitHub Desktop.
Typed actor refs snipped for Akka.NET
This file contains 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; | |
namespace Akka.Testing | |
{ | |
public interface IMyMessage { } | |
public sealed class MessageA : IMyMessage { } | |
public sealed class MessageB : IMyMessage { } | |
public class MyActor : Actor<IMyMessage> | |
{ | |
protected override void OnReceive(IMyMessage message) => message.Match() | |
.With<MessageA>(_ => Console.WriteLine("Received A")) | |
.With<MessageB>(_ => Console.WriteLine("Received B")) | |
.Default(Unhandled); | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
using (var system = Actor.ActorSystem.Create("sys")) | |
{ | |
var a = system.ActorOf(Props<IMyMessage>.Create(() => new MyActor())); | |
a.Tell(new MessageA()); | |
a.Tell("error"); // doesn't compile | |
Console.ReadLine(); | |
} | |
} | |
} | |
} |
This file contains 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.Linq.Expressions; | |
using Akka.Actor; | |
using Akka.Util; | |
namespace Akka | |
{ | |
public struct TypedRef<T> : IActorRef | |
{ | |
public TypedRef(IActorRef aref) : this() | |
{ | |
if (aref == null) throw new ArgumentNullException(nameof(aref), $"{this} has received null instead of {nameof(IActorRef)}"); | |
Ref = aref; | |
} | |
public IActorRef Ref { get; } | |
void ICanTell.Tell(object message, IActorRef sender) => Ref.Tell(message, sender); | |
public void Tell(T message, IActorRef sender) => Ref.Tell(message, sender); | |
public void Tell(T message) => Ref.Tell(message, ActorCell.GetCurrentSelfOrNoSender()); | |
public bool Equals(IActorRef other) => | |
other is TypedRef<T> ? Ref.Equals(((TypedRef<T>)other).Ref) : Ref.Equals(other); | |
public int CompareTo(IActorRef other) => | |
other is TypedRef<T> ? Ref.CompareTo(((TypedRef<T>)other).Ref) : Ref.CompareTo(other); | |
public ISurrogate ToSurrogate(ActorSystem system) => new TypeRefSurrogate<T>(Ref.ToSurrogate(system)); | |
public int CompareTo(object obj) | |
{ | |
if (obj is IActorRef) return CompareTo((IActorRef)obj); | |
throw new ArgumentException($"Cannot compare {obj} to {this}"); | |
} | |
public ActorPath Path => Ref.Path; | |
public override int GetHashCode() => Ref.GetHashCode(); | |
public override bool Equals(object obj) => obj is IActorRef && Equals((IActorRef)obj); | |
public override string ToString() => Ref.ToString(); | |
} | |
public struct Props<T> : ISurrogated | |
{ | |
public readonly Props Underlying; | |
public Props(Props props) : this() | |
{ | |
if (props == null) throw new ArgumentNullException(nameof(props), $"{this} has received null instead of {nameof(Props)}"); | |
this.Underlying = props; | |
} | |
public static Props<T> Create<TActor>(Expression<Func<TActor>> fac) where TActor : Actor<T> | |
=> new Props<T>(Props.Create(fac)); | |
public ISurrogate ToSurrogate(ActorSystem system) => new TypedPropsSurrogate<T>(Underlying.ToSurrogate(system)); | |
} | |
internal struct TypedPropsSurrogate<T> : ISurrogate | |
{ | |
public readonly ISurrogate PropsSurrogate; | |
public TypedPropsSurrogate(ISurrogate propsSurrogate) : this() | |
{ | |
PropsSurrogate = propsSurrogate; | |
} | |
public ISurrogated FromSurrogate(ActorSystem system) => new Props<T>((Props)PropsSurrogate.FromSurrogate(system)); | |
} | |
internal struct TypeRefSurrogate<T> : ISurrogate | |
{ | |
public readonly ISurrogate RefSurrogate; | |
public TypeRefSurrogate(ISurrogate refSurrogate) : this() | |
{ | |
RefSurrogate = refSurrogate; | |
} | |
public ISurrogated FromSurrogate(ActorSystem system) => new TypedRef<T>((IActorRef)RefSurrogate.FromSurrogate(system)); | |
} | |
public abstract class Actor<T> : UntypedActor | |
{ | |
protected abstract void OnReceive(T message); | |
protected override void OnReceive(object message) | |
{ | |
if (message is T) | |
OnReceive((T)message); | |
else Unhandled(message); | |
} | |
} | |
public static class TypedExtensions | |
{ | |
public static TypedRef<T> ActorOf<T>(this IActorRefFactory fac, Props<T> props) => | |
new TypedRef<T>(fac.ActorOf(props.Underlying)); | |
public static TypedRef<T> ActorOf<T>(this IActorRefFactory fac, Props<T> props, string name) => | |
new TypedRef<T>(fac.ActorOf(props.Underlying, name)); | |
public static TypedRef<T> Watch<T>(this IActorContext ctx, TypedRef<T> tref) | |
{ | |
ctx.Watch(tref.Ref); | |
return tref; | |
} | |
public static TypedRef<T> Unwatch<T>(this IActorContext ctx, TypedRef<T> tref) | |
{ | |
ctx.Unwatch(tref.Ref); | |
return tref; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment