Refactor options provider with DI support

This commit is contained in:
Sipke Schoorstra 2021-03-10 15:49:56 +01:00
parent 68675b685a
commit 0442e1e699
4 changed files with 32 additions and 29 deletions

View file

@ -33,6 +33,6 @@ namespace Elsa.Attributes
/// <summary>
/// The name of a static method that provides options.
/// </summary>
public string? OptionsProvider { get; set; }
public Type? OptionsProvider { get; set; }
}
}

View file

@ -5,7 +5,6 @@ namespace Elsa.Metadata
{
public interface IActivityPropertyOptionsProvider
{
bool SupportsProperty(PropertyInfo property);
void SupplyOptions(PropertyInfo property, JObject options);
object GetOptions(PropertyInfo property);
}
}

View file

@ -7,17 +7,18 @@ using System.Reflection;
using Elsa.Attributes;
using Elsa.Design;
using Humanizer;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq;
namespace Elsa.Metadata
{
public class ActivityDescriber : IActivityDescriber
{
private readonly IEnumerable<IActivityPropertyOptionsProvider> _optionsProviders;
private readonly IServiceProvider _serviceProvider;
public ActivityDescriber(IEnumerable<IActivityPropertyOptionsProvider> optionsProviders)
public ActivityDescriber(IServiceProvider serviceProvider)
{
_optionsProviders = optionsProviders;
_serviceProvider = serviceProvider;
}
public ActivityDescriptor? Describe(Type activityType)
@ -49,36 +50,36 @@ namespace Elsa.Metadata
private IEnumerable<ActivityPropertyDescriptor> DescribeProperties(Type activityType)
{
var properties = activityType.GetProperties();
using var scope = _serviceProvider.CreateScope();
foreach (var propertyInfo in properties)
{
var activityProperty = propertyInfo.GetCustomAttribute<ActivityPropertyAttribute>();
var activityPropertyAttribute = propertyInfo.GetCustomAttribute<ActivityPropertyAttribute>();
if (activityProperty == null)
if (activityPropertyAttribute == null)
continue;
var options = activityProperty.OptionsProvider is not null and not "" ? GetOptions(activityType, activityProperty.OptionsProvider) : activityProperty.Options;
var options = GetOptions(propertyInfo, activityPropertyAttribute, scope);
yield return new ActivityPropertyDescriptor
(
(activityProperty.Name ?? propertyInfo.Name).Pascalize(),
(activityProperty.UIHint ?? InferPropertyUIHint(propertyInfo)),
activityProperty.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
activityProperty.Hint,
(activityPropertyAttribute.Name ?? propertyInfo.Name).Pascalize(),
(activityPropertyAttribute.UIHint ?? InferPropertyUIHint(propertyInfo)),
activityPropertyAttribute.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
activityPropertyAttribute.Hint,
options
);
}
}
private object? GetOptions(Type activityType, string providerMethodName)
private object? GetOptions(PropertyInfo activityProperty, ActivityPropertyAttribute activityPropertyAttribute, IServiceScope scope)
{
var providerMethod = activityType.GetMethod(providerMethodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (activityPropertyAttribute.OptionsProvider == null)
return activityPropertyAttribute.Options;
if (providerMethod == null)
throw new MissingMethodException(activityType.Name, providerMethodName);
var options = providerMethod.Invoke(null, new object[0]);
return options;
var providerType = activityPropertyAttribute.OptionsProvider;
var provider = (IActivityPropertyOptionsProvider) ActivatorUtilities.GetServiceOrCreateInstance(scope.ServiceProvider, providerType);
return provider.GetOptions(activityProperty);
}
private string InferPropertyUIHint(PropertyInfo propertyInfo)

View file

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Elsa.ActivityResults;
using Elsa.Attributes;
using Elsa.Design;
using Elsa.Metadata;
using Elsa.Scripting.JavaScript.Events;
using Elsa.Scripting.JavaScript.Messages;
using Elsa.Scripting.JavaScript.Services;
@ -19,7 +21,7 @@ using NetBox.Extensions;
namespace Elsa.Activities.JavaScript
{
[Action(Category = "Scripting", Description = "Run JavaScript code.")]
public class RunJavaScript : Activity, INotificationHandler<RenderingTypeScriptDefinitions>
public class RunJavaScript : Activity, INotificationHandler<RenderingTypeScriptDefinitions>, IActivityPropertyOptionsProvider
{
private readonly IJavaScriptService _javaScriptService;
@ -28,7 +30,7 @@ namespace Elsa.Activities.JavaScript
_javaScriptService = javaScriptService;
}
[ActivityProperty(Hint = "The JavaScript to run.", UIHint = ActivityPropertyUIHints.CodeEditor, OptionsProvider = nameof(GetOptions))]
[ActivityProperty(Hint = "The JavaScript to run.", UIHint = ActivityPropertyUIHints.CodeEditor, OptionsProvider = typeof(RunJavaScript))]
public string? Script { get; set; }
[ActivityProperty(Hint = "The possible outcomes that can be set by the script.", UIHint = ActivityPropertyUIHints.MultiText)]
@ -60,13 +62,6 @@ namespace Elsa.Activities.JavaScript
return new CombinedResult(Output(output), new OutcomeResult(outcomes));
}
private static object GetOptions() => new
{
EditorHeight = "Large",
Context = nameof(RunJavaScript),
Syntax = JavaScriptExpressionHandler.SyntaxName
};
public Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken)
{
var context = notification.Context;
@ -79,5 +74,13 @@ namespace Elsa.Activities.JavaScript
return Task.CompletedTask;
}
object IActivityPropertyOptionsProvider.GetOptions(PropertyInfo property) =>
new
{
EditorHeight = "Large",
Context = nameof(RunJavaScript),
Syntax = JavaScriptExpressionHandler.SyntaxName
};
}
}