2017-02-15 22:05:01 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Tapeti.Config;
|
|
|
|
|
|
|
|
|
|
namespace Tapeti.Flow.Default
|
|
|
|
|
{
|
2019-08-15 11:26:55 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Default implementation for IFlowStarter.
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal class FlowStarter : IFlowStarter
|
2017-02-15 22:05:01 +01:00
|
|
|
|
{
|
2019-08-13 20:30:04 +02:00
|
|
|
|
private readonly ITapetiConfig config;
|
2017-02-15 22:05:01 +01:00
|
|
|
|
|
|
|
|
|
|
2021-05-29 21:51:58 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// </summary>
|
2019-08-15 12:04:03 +02:00
|
|
|
|
public FlowStarter(ITapetiConfig config)
|
2017-02-15 22:05:01 +01:00
|
|
|
|
{
|
|
|
|
|
this.config = config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-08-15 11:26:55 +02:00
|
|
|
|
/// <inheritdoc />
|
2019-08-15 12:04:03 +02:00
|
|
|
|
public async Task Start<TController>(Expression<Func<TController, Func<IYieldPoint>>> methodSelector) where TController : class
|
2017-02-15 22:05:01 +01:00
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await CallControllerMethod<TController>(GetExpressionMethod(methodSelector), value => Task.FromResult((IYieldPoint)value), Array.Empty<object?>()).ConfigureAwait(false);
|
2017-02-15 22:05:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-15 11:26:55 +02:00
|
|
|
|
/// <inheritdoc />
|
2019-08-15 12:04:03 +02:00
|
|
|
|
public async Task Start<TController>(Expression<Func<TController, Func<Task<IYieldPoint>>>> methodSelector) where TController : class
|
2017-02-15 22:05:01 +01:00
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await CallControllerMethod<TController>(GetExpressionMethod(methodSelector), value => (Task<IYieldPoint>)value, Array.Empty<object?>()).ConfigureAwait(false);
|
2017-02-15 22:05:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-15 11:26:55 +02:00
|
|
|
|
/// <inheritdoc />
|
2019-08-15 12:04:03 +02:00
|
|
|
|
public async Task Start<TController, TParameter>(Expression<Func<TController, Func<TParameter, IYieldPoint>>> methodSelector, TParameter parameter) where TController : class
|
2017-09-22 11:19:49 +02:00
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await CallControllerMethod<TController>(GetExpressionMethod(methodSelector), value => Task.FromResult((IYieldPoint)value), new object?[] {parameter}).ConfigureAwait(false);
|
2017-09-22 11:19:49 +02:00
|
|
|
|
}
|
2017-02-15 22:05:01 +01:00
|
|
|
|
|
2019-08-15 11:26:55 +02:00
|
|
|
|
/// <inheritdoc />
|
2019-08-15 12:04:03 +02:00
|
|
|
|
public async Task Start<TController, TParameter>(Expression<Func<TController, Func<TParameter, Task<IYieldPoint>>>> methodSelector, TParameter parameter) where TController : class
|
2017-09-22 11:19:49 +02:00
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await CallControllerMethod<TController>(GetExpressionMethod(methodSelector), value => (Task<IYieldPoint>)value, new object?[] {parameter}).ConfigureAwait(false);
|
2017-09-22 11:19:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-11-23 09:13:38 +01:00
|
|
|
|
private async Task CallControllerMethod<TController>(MethodInfo method, Func<object, Task<IYieldPoint>> getYieldPointResult, object?[] parameters) where TController : class
|
2017-02-15 22:05:01 +01:00
|
|
|
|
{
|
|
|
|
|
var controller = config.DependencyResolver.Resolve<TController>();
|
2022-11-23 09:13:38 +01:00
|
|
|
|
var result = method.Invoke(controller, parameters);
|
|
|
|
|
if (result == null)
|
|
|
|
|
throw new InvalidOperationException($"Method {method.Name} must return an IYieldPoint or Task<IYieldPoint>, got null");
|
2017-02-15 22:05:01 +01:00
|
|
|
|
|
2024-04-08 14:20:15 +02:00
|
|
|
|
var yieldPoint = await getYieldPointResult(result).ConfigureAwait(false);
|
2022-11-23 09:13:38 +01:00
|
|
|
|
|
|
|
|
|
var context = new FlowHandlerContext(config, controller, method);
|
2017-02-15 22:05:01 +01:00
|
|
|
|
|
|
|
|
|
var flowHandler = config.DependencyResolver.Resolve<IFlowHandler>();
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await flowHandler.Execute(context, yieldPoint).ConfigureAwait(false);
|
2017-02-15 22:05:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static MethodInfo GetExpressionMethod<TController, TResult>(Expression<Func<TController, Func<TResult>>> methodSelector)
|
|
|
|
|
{
|
|
|
|
|
var callExpression = (methodSelector.Body as UnaryExpression)?.Operand as MethodCallExpression;
|
|
|
|
|
var targetMethodExpression = callExpression?.Object as ConstantExpression;
|
|
|
|
|
|
|
|
|
|
var method = targetMethodExpression?.Value as MethodInfo;
|
|
|
|
|
if (method == null)
|
|
|
|
|
throw new ArgumentException("Unable to determine the starting method", nameof(methodSelector));
|
|
|
|
|
|
|
|
|
|
return method;
|
|
|
|
|
}
|
2017-09-22 11:19:49 +02:00
|
|
|
|
|
2019-08-15 12:04:03 +02:00
|
|
|
|
|
2017-09-22 11:19:49 +02:00
|
|
|
|
private static MethodInfo GetExpressionMethod<TController, TResult, TParameter>(Expression<Func<TController, Func<TParameter, TResult>>> methodSelector)
|
|
|
|
|
{
|
|
|
|
|
var callExpression = (methodSelector.Body as UnaryExpression)?.Operand as MethodCallExpression;
|
|
|
|
|
var targetMethodExpression = callExpression?.Object as ConstantExpression;
|
|
|
|
|
|
|
|
|
|
var method = targetMethodExpression?.Value as MethodInfo;
|
|
|
|
|
if (method == null)
|
|
|
|
|
throw new ArgumentException("Unable to determine the starting method", nameof(methodSelector));
|
|
|
|
|
|
|
|
|
|
return method;
|
|
|
|
|
}
|
2017-02-15 22:05:01 +01:00
|
|
|
|
}
|
|
|
|
|
}
|