RSCG – ActorSrcGen
name | ActorSrcGen |
nuget | https://www.nuget.org/packages/ActorSrcGen/ |
link | https://github.com/aabs/ActorSrcGen |
author | Andrew Matthews |
Generating source code for actors in C#.
This is how you can use ActorSrcGen .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="ActorSrcGen" Version="1.1.2" /> <PackageReference Include="ActorSrcGen.Abstractions" Version="1.1.2" /> <PackageReference Include="Gridsum.DataflowEx" Version="2.0.0" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
// See https://aka.ms/new-console-template for more information using ActorDemo; using Gridsum.DataflowEx; Person person = new Person { Name = "Andrei Ignat" }; DayWorkflow dayAndreiIgnat = new (); var input = dayAndreiIgnat.InputBlock; //async await dayAndreiIgnat.SendAsync(person); //sync while (dayAndreiIgnat.Call(person)) { await Task.Delay(100); } Console.WriteLine("Done"); Console.ReadLine();
using ActorSrcGen; using System.Diagnostics.Metrics; namespace ActorDemo; [Actor] partial class DayWorkflow { [FirstStep("StartDay")] //[Receiver] [NextStep(nameof(WashFace))] [NextStep(nameof(LogMessage))] public async Task<Person> StartDay(Person p) { await Task.Delay(1000 ); return p; } [Step] [NextStep(nameof(LogMessage))] [NextStep(nameof(Eat))] public async Task<Person> WashFace(Person p) { await Task.Delay(1000); return p; } [Step] [NextStep(nameof(LogMessage))] [NextStep(nameof(Sleep))] public async Task<Person> Eat(Person p) { await Task.Delay(1000); return p; } [NextStep(nameof(LogMessage))] public async Task<int> Sleep(Person p) { await Task.Delay(1000); return p.Name.Length; } [LastStep] public void LogMessage(Person x) { Console.WriteLine("Incoming Message: " + x?.Name); } }
namespace ActorDemo; public class Person { public string Name { get; set; } }
The code that is generated is
// Generated on 2024-06-02 #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. #pragma warning disable CS0108 // hides inherited member. using ActorSrcGen; using System.Diagnostics.Metrics; namespace ActorDemo; using System.Threading.Tasks.Dataflow; using Gridsum.DataflowEx; public partial class DayWorkflow : Dataflow<Person>, IActor<Person> { public DayWorkflow() : base(DataflowOptions.Default) { _LogMessage = new ActionBlock<Person>( (Person x) => { try { LogMessage(x); }catch{} }, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_LogMessage); _Eat = new TransformManyBlock<Person,Person>( async (Person x) => { var result = new List<Person>(); try { var newValue = await Eat(x); result.Add(newValue); }catch{} return result; }, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_Eat); _EatBC = new BroadcastBlock<Person>( (Person x) => x, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_EatBC); _WashFace = new TransformManyBlock<Person,Person>( async (Person x) => { var result = new List<Person>(); try { var newValue = await WashFace(x); result.Add(newValue); }catch{} return result; }, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_WashFace); _WashFaceBC = new BroadcastBlock<Person>( (Person x) => x, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_WashFaceBC); _StartDay = new TransformManyBlock<Person,Person>( async (Person x) => { var result = new List<Person>(); try { var newValue = await StartDay(x); result.Add(newValue); }catch{} return result; }, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_StartDay); _StartDayBC = new BroadcastBlock<Person>( (Person x) => x, new ExecutionDataflowBlockOptions() { BoundedCapacity = 5, MaxDegreeOfParallelism = 8 }); RegisterChild(_StartDayBC); _Eat.LinkTo(_EatBC, new DataflowLinkOptions { PropagateCompletion = true }); _EatBC.LinkTo(_LogMessage, new DataflowLinkOptions { PropagateCompletion = true }); _WashFace.LinkTo(_WashFaceBC, new DataflowLinkOptions { PropagateCompletion = true }); _WashFaceBC.LinkTo(_LogMessage, new DataflowLinkOptions { PropagateCompletion = true }); _WashFaceBC.LinkTo(_Eat, new DataflowLinkOptions { PropagateCompletion = true }); _StartDay.LinkTo(_StartDayBC, new DataflowLinkOptions { PropagateCompletion = true }); _StartDayBC.LinkTo(_LogMessage, new DataflowLinkOptions { PropagateCompletion = true }); _StartDayBC.LinkTo(_WashFace, new DataflowLinkOptions { PropagateCompletion = true }); } ActionBlock<Person> _LogMessage; TransformManyBlock<Person,Person> _Eat; BroadcastBlock<Person> _EatBC; TransformManyBlock<Person,Person> _WashFace; BroadcastBlock<Person> _WashFaceBC; TransformManyBlock<Person,Person> _StartDay; BroadcastBlock<Person> _StartDayBC; public override ITargetBlock<Person> InputBlock { get => _StartDay; } public bool Call(Person input) => InputBlock.Post(input); public async Task<bool> Cast(Person input) => await InputBlock.SendAsync(input); }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/ActorSrcGen
Leave a Reply