This tutorial is intended to give an introduction to using Orleankka by creating a simple greeter actor using C#.
Set up your project
Start Visual Studio and create a new C# Console Application and reference the following packages:
PM> Install-Package Orleankka.RuntimePM> Install-Package Microsoft.Orleans.Server
This will install all client and server-side packages required for demo app.
Create your first actor
First, we need to create a message type that our actor will respond to:
namespace ConsoleApplication11{ // Create a message types that your actor will respond to // and mark them with [Serializable] attribute. This is smilar to // object-oriented interface signatures (eg Greet(string who)) but with classes [Serializable] public class Greet { public string Who { get; set; } } [Serializable] public class Sleep {}}
Once we have the message type, we can create our actor:
using System;using Orleankka;namespace ConsoleApplication11{ // Create custom actor interface and implement IActorGrain public interface IGreeter : IActorGrain {} // Create actor class by inheriting from ActorGrain and implementing custom actor interface public class Greeter : ActorGrain, IGreeter { // Implement receive function (use pattern matching or any other message matching approach) public override Task<object> Receive(object message) { switch (message) { case Greet greet: return Result("Hello, {msg.Who}!"); case Sleep _: Console.WriteLine("Sleeeeping ..."); return TaskResult.Done; break; default: return Unhandled; } } }}
Now it's time to consume our actor. We need to configure Orleans and then register Orleankka. We'll be using simple localhost configuration suitable for demos.
using System;using Orleankka;using Orleankka.Playground;namespace ConsoleApplication11{ [Serializable] public class Greet { public string Who { get; set; } } [Serializable] public class Sleep {} public class Greeter : ActorGrain, IGreeter { public override Task<object> Receive(object message) { switch (message) { case Greet greet: return Result("Hello, {msg.Who}!"); case Sleep _: Console.WriteLine("Sleeeeping ..."); return TaskResult.Done; default: return Unhandled; } } } class Program { const string DemoClusterId = "localhost-demo"; const string DemoServiceId = "localhost-demo-service"; const int LocalhostSiloPort = 11111; const int LocalhostGatewayPort = 30000; static readonly IPAddress LocalhostSiloAddress = IPAddress.Loopback; static void Main(string[] args) { var host = await new SiloHostBuilder() .Configure(options => { options.ClusterId = DemoClusterId; options.ServiceId = DemoServiceId; }) .UseDevelopmentClustering(options => options.PrimarySiloEndpoint = new IPEndPoint(LocalhostSiloAddress, LocalhostSiloPort)) .ConfigureEndpoints(LocalhostSiloAddress, LocalhostSiloPort, LocalhostGatewayPort) .ConfigureApplicationParts(x => x .AddApplicationPart(Assembly.GetExecutingAssembly()) .WithCodeGeneration()) .UseOrleankka() // register Orleankka extension .Build(); // start Orleans server (silo) await host.StartAsync(); var client = new ClientBuilder() .ConfigureCluster(options => { options.ClusterId = DemoClusterId; options.ServiceId = DemoServiceId }) .UseStaticClustering(options => options.Gateways.Add(new IPEndPoint(LocalhostSiloAddress, LocalhostGatewayPort).ToGatewayUri())) .ConfigureApplicationParts(x => x .AddApplicationPart(Assembly.GetExecutingAssembly()) .WithCodeGeneration()) .UseOrleankka() .Build(); // start (connect) Orleans client await client.Connect(); // get reference to ActorSystem var system = client.ActorSystem(); // get proxy reference for IGreeter actor var greeter = system.ActorOf<IGreeter>("id"); // send query to actor (ie Ask) Console.WriteLine(await greeter.Ask<string>(new Greet {Who = "world"})); // send command to actor (ie Tell) await greeter.Tell(new Sleep()); Console.Write("\n\nPress any key to terminate ..."); Console.ReadKey(true); } }}
That is it. See more examples in a Samples directory.