From 0442e1e699ecfc6a66cde68985d6b134f12e6000 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 10 Mar 2021 15:49:56 +0100 Subject: [PATCH] Refactor options provider with DI support --- .../Attributes/ActivityPropertyAttribute.cs | 2 +- .../IActivityPropertyOptionsProvider.cs | 3 +- .../Elsa.Core/Metadata/ActivityDescriber.cs | 35 ++++++++++--------- .../Activities/RunJavaScript/RunJavaScript.cs | 21 ++++++----- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs b/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs index 2c8da6441..85dc398f0 100644 --- a/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs +++ b/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs @@ -33,6 +33,6 @@ namespace Elsa.Attributes /// /// The name of a static method that provides options. /// - public string? OptionsProvider { get; set; } + public Type? OptionsProvider { get; set; } } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Metadata/IActivityPropertyOptionsProvider.cs b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyOptionsProvider.cs index db385d8a5..156591f2c 100644 --- a/src/core/Elsa.Abstractions/Metadata/IActivityPropertyOptionsProvider.cs +++ b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyOptionsProvider.cs @@ -5,7 +5,6 @@ namespace Elsa.Metadata { public interface IActivityPropertyOptionsProvider { - bool SupportsProperty(PropertyInfo property); - void SupplyOptions(PropertyInfo property, JObject options); + object GetOptions(PropertyInfo property); } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Metadata/ActivityDescriber.cs b/src/core/Elsa.Core/Metadata/ActivityDescriber.cs index b8cde30ef..ad0bc292b 100644 --- a/src/core/Elsa.Core/Metadata/ActivityDescriber.cs +++ b/src/core/Elsa.Core/Metadata/ActivityDescriber.cs @@ -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 _optionsProviders; + private readonly IServiceProvider _serviceProvider; - public ActivityDescriber(IEnumerable optionsProviders) + public ActivityDescriber(IServiceProvider serviceProvider) { - _optionsProviders = optionsProviders; + _serviceProvider = serviceProvider; } public ActivityDescriptor? Describe(Type activityType) @@ -49,36 +50,36 @@ namespace Elsa.Metadata private IEnumerable DescribeProperties(Type activityType) { var properties = activityType.GetProperties(); + using var scope = _serviceProvider.CreateScope(); foreach (var propertyInfo in properties) { - var activityProperty = propertyInfo.GetCustomAttribute(); + var activityPropertyAttribute = propertyInfo.GetCustomAttribute(); - 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) diff --git a/src/scripting/Elsa.Scripting.JavaScript/Activities/RunJavaScript/RunJavaScript.cs b/src/scripting/Elsa.Scripting.JavaScript/Activities/RunJavaScript/RunJavaScript.cs index 42f90dd3a..d28232dde 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Activities/RunJavaScript/RunJavaScript.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Activities/RunJavaScript/RunJavaScript.cs @@ -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 + public class RunJavaScript : Activity, INotificationHandler, 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 + }; } } \ No newline at end of file