Add support for lazy initialization of output
This commit is contained in:
parent
660cfbfd05
commit
9dcae97a0e
|
|
@ -36,9 +36,13 @@ public class ExpressionExecutionContext
|
|||
public ExpressionExecutionContext? ParentContext { get; set; }
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
public MemoryBlock GetBlock(Func<MemoryBlockReference> blockReference) => GetBlock(blockReference());
|
||||
public MemoryBlock GetBlock(MemoryBlockReference blockReference) => GetMemoryDatumInternal(blockReference) ?? throw new Exception($"Failed to retrieve memory block with reference {blockReference.Id}");
|
||||
public object Get(Func<MemoryBlockReference> blockReference) => Get(blockReference());
|
||||
public object Get(MemoryBlockReference blockReference) => GetBlock(blockReference).Value!;
|
||||
public T Get<T>(Func<MemoryBlockReference> blockReference) => Get<T>(blockReference());
|
||||
public T Get<T>(MemoryBlockReference blockReference) => (T)Get(blockReference);
|
||||
public void Set(Func<MemoryBlockReference> blockReference, object? value) => Set(blockReference(), value);
|
||||
|
||||
public void Set(MemoryBlockReference blockReference, object? value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class ConfigureJavaScriptEngineWithActivityOutput : INotificationHandler<
|
|||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (register.TryGetBlock(property.Value.MemoryBlockReference.Id, out var location))
|
||||
if (register.TryGetBlock(property.Value.MemoryBlockReference().Id, out var location))
|
||||
jsActivity[property.Name] = location.Value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
using Elsa.Persistence.EntityFrameworkCore.Common;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.Persistence.EntityFrameworkCore.SqlServer.Extensions;
|
||||
|
||||
public static class DbContextOptionsBuilderExtensions
|
||||
{
|
||||
public static DbContextOptionsBuilder UseElsaSqlServer(this DbContextOptionsBuilder builder, string connectionString) =>
|
||||
builder.UseSqlServer(connectionString, db => db
|
||||
.MigrationsAssembly(typeof(DbContextOptionsBuilderExtensions).Assembly.GetName().Name)
|
||||
.MigrationsHistoryTable(ElsaDbContextBase.MigrationsHistoryTable, ElsaDbContextBase.ElsaSchema));
|
||||
public static DbContextOptionsBuilder UseElsaSqlServer(this DbContextOptionsBuilder builder, string connectionString, Action<SqlServerDbContextOptionsBuilder>? configure = default) =>
|
||||
builder.UseSqlServer(connectionString, db =>
|
||||
{
|
||||
db
|
||||
.MigrationsAssembly(typeof(DbContextOptionsBuilderExtensions).Assembly.GetName().Name)
|
||||
.MigrationsHistoryTable(ElsaDbContextBase.MigrationsHistoryTable, ElsaDbContextBase.ElsaSchema);
|
||||
|
||||
configure?.Invoke(db);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\..\common.props"/>
|
||||
<Import Project="..\..\..\configureawait.props"/>
|
||||
<Import Project="..\..\..\common.props" />
|
||||
<Import Project="..\..\..\configureawait.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
|
|
|||
14
src/modules/Elsa.Quartz/Extensions/ModuleExtensions.cs
Normal file
14
src/modules/Elsa.Quartz/Extensions/ModuleExtensions.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using Elsa.Features.Extensions;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.Quartz.Features;
|
||||
|
||||
namespace Elsa.Quartz.Extensions;
|
||||
|
||||
public static class ModuleExtensions
|
||||
{
|
||||
public static IModule UseQuartz(this IModule module, Action<QuartzFeature>? configure = default)
|
||||
{
|
||||
module.Use(configure);
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using Elsa.Features.Extensions;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.Quartz.Features;
|
||||
using Elsa.Scheduling.Features;
|
||||
|
||||
namespace Elsa.Quartz.Extensions;
|
||||
|
||||
public static class SchedulingFeatureExtensions
|
||||
{
|
||||
public static SchedulingFeature UseQuartzScheduling(this SchedulingFeature scheduling)
|
||||
{
|
||||
scheduling.Module.Use<QuartzSchedulerFeature>();
|
||||
return scheduling;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Elsa.Telnyx.Client.Models;
|
||||
using Elsa.Telnyx.Bookmarks;
|
||||
using Elsa.Telnyx.Client.Models;
|
||||
using Elsa.Telnyx.Client.Services;
|
||||
using Elsa.Telnyx.Exceptions;
|
||||
using Elsa.Telnyx.Extensions;
|
||||
|
|
@ -8,6 +9,7 @@ using Elsa.Workflows.Core;
|
|||
using Elsa.Workflows.Core.Activities.Flowchart.Attributes;
|
||||
using Elsa.Workflows.Core.Attributes;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Core.Services;
|
||||
using Elsa.Workflows.Management.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
@ -17,8 +19,7 @@ namespace Elsa.Telnyx.Activities;
|
|||
/// Dial a number or SIP URI.
|
||||
/// </summary>
|
||||
[Activity(Constants.Namespace, "Dial a number or SIP URI.", Kind = ActivityKind.Task)]
|
||||
[FlowNode("Answered", "Hangup")]
|
||||
public class Dial : ActivityBase
|
||||
public abstract class DialBase : ActivityBase
|
||||
{
|
||||
[Input(Description = "The DID or SIP URI to dial out and bridge to the given call.")]
|
||||
public Input<string?>? To { get; set; } = default!;
|
||||
|
|
@ -33,7 +34,7 @@ public class Dial : ActivityBase
|
|||
[Input(
|
||||
Description = "Enables Answering Machine Detection.",
|
||||
UIHint = InputUIHints.Dropdown,
|
||||
Options = new[] { "disabled", "detect", "detect_beep", "detect_words", "greeting_end" },
|
||||
Options = new[] { "disabled", "detect", "detect_beep", "detect_words", "greeting_end", "premium" },
|
||||
DefaultValue = "disabled")]
|
||||
public Input<string?>? AnsweringMachineDetection { get; set; } = new("disabled");
|
||||
|
||||
|
|
@ -71,16 +72,16 @@ public class Dial : ActivityBase
|
|||
}
|
||||
}
|
||||
|
||||
private async ValueTask HandleAnsweredAsync(ActivityExecutionContext context) => await context.CompleteActivityWithOutcomesAsync("Answered");
|
||||
|
||||
private async ValueTask HandleHangupAsync(ActivityExecutionContext context) => await context.CompleteActivityWithOutcomesAsync("Hangup");
|
||||
|
||||
private void HandleMachineGreetingEnded(ActivityExecutionContext context, CallMachineGreetingEndedBase payload)
|
||||
{
|
||||
context.Set(MachineDetectionResult, payload.Result);
|
||||
context.CreateBookmark();
|
||||
context.CreateBookmark(new WebhookEventBookmarkPayload(WebhookEventTypes.CallAnswered), ResumeAsync);
|
||||
context.CreateBookmark(new WebhookEventBookmarkPayload(WebhookEventTypes.CallHangup), ResumeAsync);
|
||||
}
|
||||
|
||||
protected abstract ValueTask HandleAnsweredAsync(ActivityExecutionContext context);
|
||||
protected abstract ValueTask HandleHangupAsync(ActivityExecutionContext context);
|
||||
|
||||
private async Task DialAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var telnyxOptions = context.GetRequiredService<IOptions<TelnyxOptions>>().Value;
|
||||
|
|
@ -100,8 +101,33 @@ public class Dial : ActivityBase
|
|||
AnsweringMachineDetection.Get(context),
|
||||
ClientState: clientState
|
||||
);
|
||||
|
||||
|
||||
var telnyxClient = context.GetRequiredService<ITelnyxClient>();
|
||||
await telnyxClient.Calls.DialAsync(request, context.CancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
[FlowNode("Answered", "Hangup")]
|
||||
public class FlowDial : DialBase
|
||||
{
|
||||
protected override async ValueTask HandleAnsweredAsync(ActivityExecutionContext context) => await context.CompleteActivityWithOutcomesAsync("Answered");
|
||||
protected override async ValueTask HandleHangupAsync(ActivityExecutionContext context) => await context.CompleteActivityWithOutcomesAsync("Hangup");
|
||||
}
|
||||
|
||||
public class Dial : DialBase
|
||||
{
|
||||
[Port] public IActivity? Answered { get; set; }
|
||||
[Port] public IActivity? Hangup { get; set; }
|
||||
|
||||
protected override ValueTask HandleAnsweredAsync(ActivityExecutionContext context)
|
||||
{
|
||||
context.ScheduleActivity(Answered);
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
protected override ValueTask HandleHangupAsync(ActivityExecutionContext context)
|
||||
{
|
||||
context.ScheduleActivity(Hangup);
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ internal static class WebhookEventTypes
|
|||
public const string CallInitiated = "call.initiated";
|
||||
public const string CallMachineGreetingEnded = "call.machine.greeting.ended";
|
||||
public const string CallMachinePremiumGreetingEnded = "call.machine.premium.greeting.ended";
|
||||
public const string CallMachineDetectionEnded = "call.machine.detection.ended";
|
||||
public const string CallMachinePremiumDetectionEnded = "call.machine.premium.detection.ended";
|
||||
public const string CallPlaybackStarted = "call.playback.started";
|
||||
public const string CallPlaybackEnded = "call.playback.ended";
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ public class ForEach<T> : ForEach
|
|||
[Input]
|
||||
public new Input<ICollection<T>> Items
|
||||
{
|
||||
get => new(base.Items.Expression, base.Items.MemoryBlockReference);
|
||||
set => base.Items = new Input<ICollection<object>>(value.Expression, value.MemoryBlockReference);
|
||||
get => new(base.Items.Expression, base.Items.MemoryBlockReference());
|
||||
set => base.Items = new Input<ICollection<object>>(value.Expression, value.MemoryBlockReference());
|
||||
}
|
||||
|
||||
public new Output<T?> CurrentValue
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public static class ActivityExecutionContextExtensions
|
|||
|
||||
foreach (var input in assignedInputs)
|
||||
{
|
||||
var memoryReference = input.MemoryBlockReference;
|
||||
var memoryReference = input.MemoryBlockReference();
|
||||
var value = await evaluator.EvaluateAsync(input, expressionExecutionContext);
|
||||
memoryReference.Set(context, value);
|
||||
}
|
||||
|
|
@ -96,9 +96,9 @@ public static class ActivityExecutionContextExtensions
|
|||
var evaluator = context.GetRequiredService<IExpressionEvaluator>();
|
||||
var expressionExecutionContext = context.ExpressionExecutionContext;
|
||||
|
||||
var locationReference = input.MemoryBlockReference;
|
||||
var memoryBlockReference = input.MemoryBlockReference();
|
||||
var value = await evaluator.EvaluateAsync(input, expressionExecutionContext);
|
||||
locationReference.Set(context, value);
|
||||
memoryBlockReference.Set(context, value);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
|
@ -151,9 +151,9 @@ public static class ActivityExecutionContextExtensions
|
|||
public static async Task<T?> EvaluateAsync<T>(this ActivityExecutionContext context, Input<T> input)
|
||||
{
|
||||
var evaluator = context.GetRequiredService<IExpressionEvaluator>();
|
||||
var locationReference = input.MemoryBlockReference;
|
||||
var memoryBlockReference = input.MemoryBlockReference();
|
||||
var value = await evaluator.EvaluateAsync(input, context.ExpressionExecutionContext);
|
||||
locationReference.Set(context, value);
|
||||
memoryBlockReference.Set(context, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,6 @@ public static class ExpressionExecutionContextExtensions
|
|||
|
||||
public static void Set(this ExpressionExecutionContext context, Output? output, object? value)
|
||||
{
|
||||
if(output != null) context.Set(output.MemoryBlockReference, value);
|
||||
if(output != null) context.Set(output.MemoryBlockReference(), value);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,24 +36,33 @@ public class IdentityGraphService : IIdentityGraphService
|
|||
private void AssignInputOutputs(IActivity activity)
|
||||
{
|
||||
var inputs = activity.GetInputs();
|
||||
var assignedInputs = inputs.Where(x => x.MemoryBlockReference != null! && x.MemoryBlockReference.Id == null!).ToList();
|
||||
|
||||
var assignedInputs = inputs.Where(x =>
|
||||
{
|
||||
var memoryBlockReference = x.MemoryBlockReference();
|
||||
return memoryBlockReference.Id == null!;
|
||||
}).ToList();
|
||||
|
||||
var seed = 0;
|
||||
|
||||
foreach (var input in assignedInputs)
|
||||
{
|
||||
var locationReference = input.MemoryBlockReference;
|
||||
|
||||
var locationReference = input.MemoryBlockReference();
|
||||
locationReference.Id = $"{activity.Id}:input-{++seed}";
|
||||
}
|
||||
|
||||
seed = 0;
|
||||
var outputs = activity.GetOutputs();
|
||||
var assignedOutputs = outputs.Where(x => x.Value.MemoryBlockReference != null! && x.Value.MemoryBlockReference.Id == null!).ToList();
|
||||
|
||||
var assignedOutputs = outputs.Where(x =>
|
||||
{
|
||||
var memoryBlockReference = x.Value.MemoryBlockReference();
|
||||
return memoryBlockReference != null! && memoryBlockReference.Id == null!;
|
||||
}).ToList();
|
||||
|
||||
foreach (var output in assignedOutputs)
|
||||
{
|
||||
var memoryReference = output.Value.MemoryBlockReference;
|
||||
|
||||
var memoryReference = output.Value.MemoryBlockReference();
|
||||
memoryReference.Id = $"{activity.Id}:output-{++seed}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ public class ActivityExecutionContext
|
|||
public T? GetService<T>() where T : notnull => WorkflowExecutionContext.GetService<T>();
|
||||
public IEnumerable<T> GetServices<T>() where T : notnull => WorkflowExecutionContext.GetServices<T>();
|
||||
public object? GetService(Type serviceType) => WorkflowExecutionContext.GetService(serviceType);
|
||||
public T? Get<T>(Input<T>? input) => input == null ? default : Get<T>(input.MemoryBlockReference);
|
||||
public T? Get<T>(Input<T>? input) => input == null ? default : Get<T>(input.MemoryBlockReference());
|
||||
|
||||
public object? Get(MemoryBlockReference blockReference)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,14 +4,18 @@ namespace Elsa.Workflows.Core.Models;
|
|||
|
||||
public abstract class Argument
|
||||
{
|
||||
protected Argument(){}
|
||||
|
||||
protected Argument(MemoryBlockReference memoryBlockReference /*, Func<object?, object?>? valueConverter = default*/)
|
||||
protected Argument()
|
||||
{
|
||||
MemoryBlockReference = memoryBlockReference;
|
||||
//ValueConverter = valueConverter;
|
||||
}
|
||||
|
||||
public MemoryBlockReference MemoryBlockReference { get; set; } = default!;
|
||||
//public Func<object?, object?>? ValueConverter { get; set; }
|
||||
protected Argument(MemoryBlockReference memoryBlockReference) : this(() => memoryBlockReference)
|
||||
{
|
||||
}
|
||||
|
||||
protected Argument(Func<MemoryBlockReference> memoryBlockReference)
|
||||
{
|
||||
MemoryBlockReference = memoryBlockReference;
|
||||
}
|
||||
|
||||
public Func<MemoryBlockReference> MemoryBlockReference { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ public class Input<T> : Input
|
|||
{
|
||||
}
|
||||
|
||||
public Input(Output output) : base(new OutputExpression(output), output.MemoryBlockReference, typeof(T))
|
||||
public Input(Output output) : base(new OutputExpression(output), output.MemoryBlockReference(), typeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ public class Output : Argument
|
|||
{
|
||||
}
|
||||
|
||||
public Output(MemoryBlockReference locationBlockReference) : base(locationBlockReference)
|
||||
public Output(MemoryBlockReference memoryBlockReference) : base(memoryBlockReference)
|
||||
{
|
||||
}
|
||||
|
||||
public Output(Func<MemoryBlockReference> memoryBlockReference) : base(memoryBlockReference)
|
||||
{
|
||||
}
|
||||
|
||||
//public ICollection<MemoryReference> Targets { get; } = new List<MemoryReference>();
|
||||
}
|
||||
|
||||
public class Output<T> : Output
|
||||
|
|
@ -21,7 +23,11 @@ public class Output<T> : Output
|
|||
{
|
||||
}
|
||||
|
||||
public Output(MemoryBlockReference locationBlockReference) : base(locationBlockReference)
|
||||
public Output(MemoryBlockReference memoryBlockReference) : base(memoryBlockReference)
|
||||
{
|
||||
}
|
||||
|
||||
public Output(Func<MemoryBlockReference> memoryBlockReference) : base(memoryBlockReference)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ public class OutputJsonConverter<T> : JsonConverter<Output<T>?>
|
|||
Type = valueTypeAlias,
|
||||
MemoryReference = value == null ? null : new
|
||||
{
|
||||
Id = value.MemoryBlockReference.Id
|
||||
Id = value.MemoryBlockReference().Id
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ public class TriggerIndexer : ITriggerIndexer
|
|||
// Evaluate activity inputs before requesting trigger data.
|
||||
foreach (var input in assignedInputs)
|
||||
{
|
||||
var locationReference = input.MemoryBlockReference;
|
||||
var locationReference = input.MemoryBlockReference();
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using Elsa.Workflows.Runtime.Services;
|
|||
namespace Elsa.Workflows.Runtime.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Takes care of persisting a workflow instance after workflow execution.
|
||||
/// Takes care of persisting workflow execution log entries.
|
||||
/// </summary>
|
||||
public class PersistWorkflowExecutionLogMiddleware : WorkflowExecutionMiddleware
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using Elsa.Workflows.Core.Models;
|
|||
|
||||
public class AskAge : Composite<int>
|
||||
{
|
||||
private readonly WriteLine _prompt = new();
|
||||
private readonly Variable<string> _age = new();
|
||||
|
||||
public Input<string> Prompt { get; set; } = new("Please tell me your age:");
|
||||
|
|
@ -16,17 +15,12 @@ public class AskAge : Composite<int>
|
|||
Variables = { _age },
|
||||
Activities =
|
||||
{
|
||||
_prompt,
|
||||
new WriteLine(context => Prompt.Get(context)),
|
||||
new ReadLine(_age)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void ConfigureActivities(ActivityExecutionContext context)
|
||||
{
|
||||
_prompt.Text = Prompt;
|
||||
}
|
||||
|
||||
protected override void OnCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
{
|
||||
var age = _age.Get<int>(context);
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Activities;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
|
||||
public class AskDetails : Composite<Person>
|
||||
{
|
||||
private readonly Variable<string> _name = new();
|
||||
private readonly Variable<int> _age = new();
|
||||
|
||||
public Input<string> NamePrompt { get; set; } = new("Please tell me your name:");
|
||||
public Input<string> AgePrompt { get; set; } = new("Please tell me your age:");
|
||||
|
||||
public AskDetails()
|
||||
{
|
||||
Root = new Sequence
|
||||
{
|
||||
Variables = { _name, _age },
|
||||
Activities =
|
||||
{
|
||||
new AskName
|
||||
{
|
||||
Prompt = new Input<string>(context => NamePrompt.Get(context)),
|
||||
Result = new Output(() => _name)
|
||||
},
|
||||
new AskAge
|
||||
{
|
||||
Prompt = new Input<string>(context => AgePrompt.Get(context)),
|
||||
Result = new Output(() => _age)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
{
|
||||
var name = _name.Get<string>(context)!;
|
||||
var age = _age.Get<int>(context);
|
||||
var person = new Person(name, age);
|
||||
|
||||
context.Set(Result, person);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Activities;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
|
||||
public class AskName : Composite<string>
|
||||
{
|
||||
private readonly Variable<string> _name = new();
|
||||
|
||||
public Input<string> Prompt { get; set; } = new("Please tell me your name:");
|
||||
|
||||
public AskName()
|
||||
{
|
||||
Root = new Sequence
|
||||
{
|
||||
Variables = { _name },
|
||||
Activities =
|
||||
{
|
||||
new WriteLine(context => Prompt.Get(context)),
|
||||
new ReadLine(_name)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
{
|
||||
var name = _name.Get<string>(context);
|
||||
context.Set(Result, name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
public record Person(string Name, int Age);
|
||||
|
|
@ -14,20 +14,25 @@ services.AddElsa();
|
|||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
// Declare a workflow variable for use in the workflow.
|
||||
var ageVariable = new Variable<int>();
|
||||
var personVariable = new Variable<Person>();
|
||||
|
||||
// Declare a workflow.
|
||||
var workflow = new Sequence
|
||||
{
|
||||
Variables = { ageVariable },
|
||||
Variables = { personVariable },
|
||||
Activities =
|
||||
{
|
||||
new AskAge
|
||||
new AskDetails()
|
||||
{
|
||||
Prompt = new Input<string>("What's your age?"),
|
||||
Result = new Output(ageVariable)
|
||||
NamePrompt = new Input<string>("What's your name?"),
|
||||
AgePrompt = new Input<string>("What's your age?"),
|
||||
Result = new Output(personVariable)
|
||||
},
|
||||
new WriteLine(context => $"The age you told me is: {ageVariable.Get(context)}")
|
||||
new WriteLine(context =>
|
||||
{
|
||||
var person = personVariable.Get(context)!;
|
||||
return $"Your name is {person.Name} and you are {person.Age} years old.";
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue