Go C#

Getting started with Proto.Actor

This tutorial is intended to give an introduction to using Proto.Actor by creating a simple greeter actor using C#.

getting started

Set up your project

First, we need to start Visual Studio and create a new C# Console Application. Once we have our console application, we need to install Proto.Actor package. In order to do this open up the Package Manager Console and type:

PM> Install-Package Proto.Actor

Then we need to add using Proto.Actor statement:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Add these two lines
using Proto;

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Create your first actor

First, let’s create a class Greet. This class is the message type that will be sent to the actor and that the actor will respond. The instance of the message class must be immutable. You can read more about what messages are in Proto.Actor here. In the class Greet, we create the property Who, which has a public getter and a private setter. The property will be set in the constructor when creating an instance of the class. This way we can guarantee that the Who property will not change after the creation of the instance of class Greet.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Proto;

namespace ConsoleApplication11
{
    // Create an (immutable) message type that your actor will respond to
    public class Greet
    {
        public Greet(string who)
        {
            Who = who;
        }
        public string Who { get;private set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Once we have the message type, we can create our actor. To do this, we create class GreetingActor that inherits from the IActor interface. In this class, we need to implement an asynchronous method ReceiveAsync that has IContext parameter. If the incoming IContext contains a message of the Greet type, then we need to respond to it. Otherwise, no action is required.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Proto;

namespace ConsoleApplication11
{
    public class Greet
    {
        public Greet(string who)
        {
            Who = who;
        }
        public string Who { get;private set; }
    }

    // Create the actor class
    public class GreetingActor : IActor
    {
        public Task ReceiveAsync(IContext ctx)
        {
            if (ctx.Message is Greet greet)
            {
                // Tell the actor to respond
                // to the Greet message
                Console.WriteLine($"Hello {greet.Who}"); 
            }
            return Task.CompletedTask;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Now it’s time to consume our actor, we do so by calling Spawn. First, let’s create Props that determine how the actor will be created. Read more about what Prop is. Then spawn the actor using created Props and send a message of Greet type to it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Proto;

namespace ConsoleApplication11
{
    public class Greet
    {
        public Greet(string who)
        {
            Who = who;
        }
        public string Who { get;private set; }
    }

    // Create the actor class
    public class GreetingActor : IActor
    {
        public Task ReceiveAsync(IContext ctx)
        {
            if (ctx.Message is Greet greet)
            {
                // Tell the actor to respond
                // to the Greet message
                Console.WriteLine($"Hello {greet.Who}"); 
            }
            return Task.CompletedTask;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var system = new ActorSystem();
            var props = Props.FromProducer(() => new GreetingActor());
            var greeter = system.Root.Spawn(props);

            // Send a message to the actor
            system.Root.Send(greeter, new Greet("World"));

            // This prevents the app from exiting
            // before the async work is done
            Console.ReadLine();
        }
    }
}

That is it, your actor is now ready to consume messages sent from any number of calling threads.

Icon