Rename GetVariableByName to GetVariable and increase XML coverage

This commit is contained in:
Sipke Schoorstra 2023-07-31 20:03:41 +02:00
parent 98f48f3933
commit e1784f7f6c
10 changed files with 113 additions and 19 deletions

View file

@ -1,5 +1,8 @@
namespace Elsa.Expressions.Contracts;
/// <summary>
/// Marker interface for expression types.
/// </summary>
public interface IExpression
{
}

View file

@ -2,7 +2,17 @@ using Elsa.Expressions.Models;
namespace Elsa.Expressions.Contracts;
/// <summary>
/// Evaluates an expression.
/// </summary>
public interface IExpressionHandler
{
/// <summary>
/// Evaluates an expression.
/// </summary>
/// <param name="expression">The expression to evaluate.</param>
/// <param name="returnType">The expected return type.</param>
/// <param name="context">The context in which the expression is evaluated.</param>
/// <returns>The result of the evaluation.</returns>
ValueTask<object?> EvaluateAsync(IExpression expression, Type returnType, ExpressionExecutionContext context);
}

View file

@ -1,7 +1,21 @@
namespace Elsa.Expressions.Contracts;
/// <summary>
/// A registry of expression handlers.
/// </summary>
public interface IExpressionHandlerRegistry
{
void Register(Type expression, Type handler);
IExpressionHandler? GetHandler(IExpression input);
/// <summary>
/// Registers an expression handler for the specified expression type.
/// </summary>
/// <param name="expressionType">The expression type.</param>
/// <param name="handler">The expression handler type.</param>
void Register(Type expressionType, Type handler);
/// <summary>
/// Returns an expression handler for the specified expression.
/// </summary>
/// <param name="expression">The expression.</param>
/// <returns>An expression handler or <c>null</c> if no handler was found.</returns>
IExpressionHandler? GetHandler(IExpression expression);
}

View file

@ -3,23 +3,68 @@ using Elsa.Expressions.Contracts;
namespace Elsa.Expressions.Models;
/// <summary>
/// Describes an expression syntax.
/// </summary>
public class ExpressionSyntaxDescriptor
{
/// <summary>
/// Gets or sets the syntax name.
/// </summary>
public string Syntax { get; init; } = default!;
/// <summary>
/// Gets or sets the expression type.
/// </summary>
public Type Type { get; init; } = default!;
/// <summary>
/// Gets or sets a delegate that creates an expression.
/// </summary>
public Func<ExpressionConstructorContext, IExpression> CreateExpression { get; init; } = default!;
/// <summary>
/// Gets or sets a delegate that creates a memory block reference.
/// </summary>
public Func<BlockReferenceConstructorContext, MemoryBlockReference> CreateBlockReference { get; init; } = default!;
/// <summary>
/// Gets or sets a delegate that creates a serializable object.
/// </summary>
public Func<SerializableObjectConstructorContext, object> CreateSerializableObject { get; init; } = default!;
}
/// <summary>
/// Contextual information for creating an expression.
/// </summary>
/// <param name="Element">The JSON element containing the expression.</param>
/// <param name="SerializerOptions">The JSON serializer options.</param>
public record ExpressionConstructorContext(JsonElement Element, JsonSerializerOptions SerializerOptions);
/// <summary>
/// Contextual information for creating a memory block reference.
/// </summary>
/// <param name="Expression">The expression.</param>
public record BlockReferenceConstructorContext(IExpression Expression)
{
/// <summary>
/// Gets the expression.
/// </summary>
/// <typeparam name="T">The expression type.</typeparam>
/// <returns>The expression.</returns>
public T GetExpression<T>() => (T)Expression;
}
/// <summary>
/// Contextual information for creating a serializable object.
/// </summary>
/// <param name="Expression">The expression.</param>
public record SerializableObjectConstructorContext(IExpression Expression)
{
/// <summary>
/// Gets the expression.
/// </summary>
/// <typeparam name="T">The expression type.</typeparam>
/// <returns>The expression.</returns>
public T GetExpression<T>() => (T)Expression;
}

View file

@ -1,28 +1,50 @@
namespace Elsa.Expressions.Models;
/// <summary>
/// A literal expression that represents a constant value.
/// </summary>
public class Literal : MemoryBlockReference
{
/// <inheritdoc />
public Literal()
{
}
/// <inheritdoc />
public Literal(object? value, string? id = default) : base(id!)
{
Value = value;
}
/// <summary>
/// Gets the value of the literal.
/// </summary>
public object? Value { get; }
/// <inheritdoc />
public override MemoryBlock Declare() => new();
/// <summary>
/// Creates a literal expression from a value.
/// </summary>
/// <param name="value">The value.</param>
/// <typeparam name="T">The value type.</typeparam>
/// <returns>A literal expression.</returns>
public static Literal From<T>(T value) => new Literal<T>(value);
}
/// <summary>
/// A literal expression that represents a constant value.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public class Literal<T> : Literal
{
/// <inheritdoc />
public Literal()
{
}
/// <inheritdoc />
public Literal(T value, string? id = default) : base(value!, id)
{
}

View file

@ -17,11 +17,11 @@ public class ExpressionHandlerRegistry : IExpressionHandlerRegistry
private IDictionary<Type, Type> Dictionary { get; }
public void Register(Type expression, Type handler) => Dictionary.Add(expression, handler);
public void Register(Type expressionType, Type handler) => Dictionary.Add(expressionType, handler);
public IExpressionHandler? GetHandler(IExpression input)
public IExpressionHandler? GetHandler(IExpression expression)
{
var expressionType = input.GetType();
var expressionType = expression.GetType();
if (expressionType.IsConstructedGenericType)
expressionType = expressionType.BaseType;

View file

@ -143,7 +143,7 @@ public static class ActivityExecutionContextExtensions
/// <param name="name">The name of the variable.</param>
/// <typeparam name="T">The type of the variable.</typeparam>
/// <returns>The variable if found, otherwise null.</returns>
public static T? GetVariableByName<T>(this ActivityExecutionContext context, string name) => context.ExpressionExecutionContext.GetVariableByName<T?>(name);
public static T? GetVariable<T>(this ActivityExecutionContext context, string name) => context.ExpressionExecutionContext.GetVariable<T?>(name);
/// <summary>
/// Returns a dictionary of variable keys and their values across scopes.

View file

@ -45,9 +45,9 @@ public static class ExpressionExecutionContextExtensions
public static T? Get<T>(this ExpressionExecutionContext context, Input<T>? input) => input != null ? context.GetBlock(input.MemoryBlockReference).Value.ConvertTo<T>() : default;
public static T? Get<T>(this ExpressionExecutionContext context, Output output) => context.GetBlock(output.MemoryBlockReference).Value.ConvertTo<T>();
public static object? Get(this ExpressionExecutionContext context, Output output) => context.GetBlock(output.MemoryBlockReference).Value;
public static T? GetVariableByName<T>(this ExpressionExecutionContext context, string name) => (T?)context.GetVariableByName(name)?.Value;
public static T? GetVariable<T>(this ExpressionExecutionContext context, string name) => (T?)context.GetVariable(name)?.Value;
private static Variable? GetVariableByName(this ExpressionExecutionContext context, string name)
private static Variable? GetVariable(this ExpressionExecutionContext context, string name)
{
foreach (var block in context.Memory.Blocks.Where(b => b.Value.Metadata is VariableBlockMetadata))
{
@ -56,12 +56,12 @@ public static class ExpressionExecutionContextExtensions
return metadata.Variable;
}
return context.ParentContext?.GetVariableByName(name);
return context.ParentContext?.GetVariable(name);
}
public static Variable CreateVariable<T>(this ExpressionExecutionContext context, string name, T? value, Type? storageDriverType = null, Action<MemoryBlock>? configure = default)
{
var existingVariable = context.GetVariableByName(name);
var existingVariable = context.GetVariable(name);
if(existingVariable != null)
throw new Exception($"Variable {name} already exists in the context.");
@ -76,7 +76,7 @@ public static class ExpressionExecutionContextExtensions
public static Variable SetVariable<T>(this ExpressionExecutionContext context, string name, T? value, Action<MemoryBlock>? configure = default)
{
var variable = context.GetVariableByName(name);
var variable = context.GetVariable(name);
if(variable is null)
throw new Exception($"Variable {name} not found in the context.");

View file

@ -68,9 +68,9 @@ class SetGetNamedVariableWorkflow : WorkflowBase
Activities =
{
new WriteLine(context => $"Foo = {context.GetVariableByName<string>("Foo")}"),
new WriteLine(context => $"Foo = {context.GetVariable<string>("Foo")}"),
Inline.From(context => context.SetVariable("Foo", "Baz")),
new WriteLine(context => $"Foo = {context.GetVariableByName<string>("Foo")}"),
new WriteLine(context => $"Foo = {context.GetVariable<string>("Foo")}"),
}
};
}

View file

@ -7,7 +7,7 @@ namespace Elsa.Workflows.Core.UnitTests;
public class ExpressionExecutionContextExtensionsTests
{
[Fact]
public void GetVariableByName_ReturnsVariable_WhenVariableExists()
public void GetVariable_ReturnsVariable_WhenVariableExists()
{
// Arrange
var variable = new Variable("test", 5);
@ -19,21 +19,21 @@ public class ExpressionExecutionContextExtensionsTests
var context = new ExpressionExecutionContext(null!, memoryRegister);
// Act
var result = context.GetVariableByName<int>("test");
var result = context.GetVariable<int>("test");
// Assert
Assert.Equal(5, result);
}
[Fact]
public void GetVariableByName_ReturnsNull_WhenVariableDoesNotExist()
public void GetVariable_ReturnsNull_WhenVariableDoesNotExist()
{
// Arrange
var memoryRegister = new MemoryRegister(new Dictionary<string, MemoryBlock>());
var context = new ExpressionExecutionContext(null!, memoryRegister);
// Act
var result = context.GetVariableByName<string>("nonexistent");
var result = context.GetVariable<string>("nonexistent");
// Assert
Assert.Null(result);
@ -66,7 +66,7 @@ public class ExpressionExecutionContextExtensionsTests
context.CreateVariable("newVariable", 10);
// Assert
var variable = context.GetVariableByName<int>("newVariable");
var variable = context.GetVariable<int>("newVariable");
Assert.Equal(10, variable);
}
@ -97,7 +97,7 @@ public class ExpressionExecutionContextExtensionsTests
context.SetVariable("test", 10);
// Assert
var updatedVariable = context.GetVariableByName<int>("test");
var updatedVariable = context.GetVariable<int>("test");
Assert.Equal(10, updatedVariable);
}
}