diff --git a/src/core/Elsa.Abstractions/Models/Variables.cs b/src/core/Elsa.Abstractions/Models/Variables.cs index b1af0644d..03c37133e 100644 --- a/src/core/Elsa.Abstractions/Models/Variables.cs +++ b/src/core/Elsa.Abstractions/Models/Variables.cs @@ -1,13 +1,32 @@ using System; +using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Elsa.Models { - public class Variables : Dictionary + public class Variables : IDictionary { public static readonly Variables Empty = new Variables(); + private ConcurrentDictionary objects = new ConcurrentDictionary(); + + public ICollection Keys => objects.Keys; + + public ICollection Values + { + get + { + return objects.Values.Select(o => GetJToken(o)).ToList(); + } + } + + public int Count => objects.Count; + + public bool IsReadOnly => false; + public Variables() { @@ -25,6 +44,54 @@ namespace Elsa.Models } } + public JToken this[string key] + { + get + { + return GetJToken(key); + } + set + { + Set(key, value); + } + } + + private void Set(string key, object value) + { + objects.TryAdd(key, value); + } + + private JToken GetJToken(string key) + { + object value; + JToken token; + objects.TryGetValue(key, out value); + + if (value != null && value.GetType() != typeof(JToken)) + token = JToken.FromObject(value); + else + token = (JToken)value; + + return token; + } + + private JToken GetJToken(object value) + { + JToken token; + + if (value != null && value.GetType() != typeof(JToken)) + token = JToken.FromObject(value); + else + token = (JToken)value; + + return token; + } + + public bool ContainsKey(string key) + { + return objects.ContainsKey(key); + } + public JToken GetVariable(string name) { return ContainsKey(name) ? this[name] : default; @@ -32,22 +99,25 @@ namespace Elsa.Models public object GetVariable(string name, Type type) { - var value = ContainsKey(name) ? this[name] : default; - return value == null ? default : value.ToObject(type); + object value; + objects.TryGetValue(name, out value); + return value == null ? default : value; } public T GetVariable(string name) { - var value = ContainsKey(name) ? this[name] : default; - return value == null ? default : value.ToObject(); + object value; + objects.TryGetValue(name, out value); + return value == null ? default : (T)value; } public JToken SetVariable(string name, object value) { - return this[name] = JToken.FromObject(value); + objects.TryAdd(name, value); + return GetJToken(value); } - public void SetVariables(Variables variables) => + public void SetVariables(Variables variables) => SetVariables((IEnumerable>)variables); public void SetVariables(IEnumerable> variables) @@ -60,5 +130,80 @@ namespace Elsa.Models { return ContainsKey(name); } + + public void Add(string key, JToken value) + { + Set(key, value); + } + + bool IDictionary.ContainsKey(string key) + { + return objects.ContainsKey(key); + } + + public bool Remove(string key) + { + object outRemove; + return objects.TryRemove(key, out outRemove); + } + + public bool TryGetValue(string key, out JToken value) + { + object valueObject; + bool found = objects.TryGetValue(key, out valueObject); + + if (found) + value = GetJToken(valueObject); + else + value = null; + + return found; + } + + public void Add(KeyValuePair item) + { + objects.TryAdd(item.Key, item.Value); + } + + public void Clear() + { + objects.Clear(); + } + + public bool Contains(KeyValuePair item) + { + KeyValuePair searchItem = new KeyValuePair(item.Key, item.Value); + return objects.Contains(searchItem); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + var newArray = + objects.Select( + kv => + new KeyValuePair(kv.Key, GetJToken(kv.Key)) + ).ToArray(); + + newArray.CopyTo(array, arrayIndex); + } + + public bool Remove(KeyValuePair item) + { + object removeObject; + return objects.TryRemove(item.Key, out removeObject); + } + + public IEnumerator> GetEnumerator() + { + return objects.Select( + kv => + new KeyValuePair(kv.Key, GetJToken(kv.Key)) + ).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Models/WorkflowExecutionScope.cs b/src/core/Elsa.Abstractions/Models/WorkflowExecutionScope.cs index 6d3ab0ce7..da4369f2d 100644 --- a/src/core/Elsa.Abstractions/Models/WorkflowExecutionScope.cs +++ b/src/core/Elsa.Abstractions/Models/WorkflowExecutionScope.cs @@ -13,11 +13,7 @@ namespace Elsa.Models public JToken LastResult { get; set; } public Variables Variables { get; } - public void SetVariable(string variableName, object value) - { - Variables[variableName] = JToken.FromObject(value); - } - + public void SetVariable(string variableName, object value) => Variables.SetVariable(variableName, value); public T GetVariable(string name) => Variables.GetVariable(name); public object GetVariable(string name, Type type) => Variables.GetVariable(name, type); public JToken GetVariable(string name) => Variables.GetVariable(name);