diff --git a/src/Lanceur.Core/Models/MacroQueryResult.cs b/src/Lanceur.Core/Models/MacroQueryResult.cs new file mode 100644 index 00000000..1b4e8c64 --- /dev/null +++ b/src/Lanceur.Core/Models/MacroQueryResult.cs @@ -0,0 +1,11 @@ +namespace Lanceur.Core.Models +{ + public abstract class MacroQueryResult : SelfExecutableQueryResult + { + #region Methods + + public abstract SelfExecutableQueryResult Clone(); + + #endregion Methods + } +} \ No newline at end of file diff --git a/src/Lanceur.Infra/Managers/MacroManager.cs b/src/Lanceur.Infra/Managers/MacroManager.cs index 97ece99b..10f38542 100644 --- a/src/Lanceur.Infra/Managers/MacroManager.cs +++ b/src/Lanceur.Infra/Managers/MacroManager.cs @@ -4,6 +4,7 @@ using System.Reflection; using Lanceur.Core.Repositories; using Lanceur.Infra.Utils; +using Lanceur.SharedKernel.Mixins; namespace Lanceur.Infra.Managers { @@ -46,7 +47,7 @@ public QueryResult Handle(QueryResult item) return null; } - var macro = MacroInstances[alias.GetMacroName()]; + var macro = MacroInstances[alias.GetMacroName()].Clone(); macro.Name = alias.Name; macro.Parameters = alias.Parameters; return macro; diff --git a/src/Lanceur.Infra/Managers/MacroManagerCache.cs b/src/Lanceur.Infra/Managers/MacroManagerCache.cs index c4d467b9..27084d53 100644 --- a/src/Lanceur.Infra/Managers/MacroManagerCache.cs +++ b/src/Lanceur.Infra/Managers/MacroManagerCache.cs @@ -13,7 +13,7 @@ public abstract class MacroManagerCache { #region Fields - private static Dictionary _macroInstances; + private static Dictionary _macroInstances; private readonly Assembly _asm; private readonly IDbRepository _dataService; @@ -34,7 +34,7 @@ internal MacroManagerCache(Assembly asm, IAppLoggerFactory logFactory, IDbReposi protected IAppLogger Log { get; } - protected Dictionary MacroInstances + protected Dictionary MacroInstances { get { @@ -54,11 +54,11 @@ private void LoadMacros() var found = from t in _asm.GetTypes() where t.GetCustomAttributes().Any() select t; - var macroInstances = new Dictionary(); + var macroInstances = new Dictionary(); foreach (var type in found) { var instance = Activator.CreateInstance(type); - if (instance is not SelfExecutableQueryResult alias) continue; + if (instance is not MacroQueryResult alias) continue; var name = alias.Name = (type.GetCustomAttribute(typeof(MacroAttribute)) as MacroAttribute)?.Name; name = name?.ToUpper().Replace("@", string.Empty) ?? string.Empty; diff --git a/src/Lanceur.Infra/Services/SearchService.cs b/src/Lanceur.Infra/Services/SearchService.cs index f0994240..f152185e 100644 --- a/src/Lanceur.Infra/Services/SearchService.cs +++ b/src/Lanceur.Infra/Services/SearchService.cs @@ -73,7 +73,7 @@ public IEnumerable Search(Cmdline query) // If there's an exact match, promote it to the top // of the list. - var orderedResults = SetupAndSort(results).ToArray(); + var orderedResults = SetupAndSort(results).ToList(); var match = (from r in orderedResults where r.Name == query.Name select r).FirstOrDefault(); diff --git a/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs b/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs new file mode 100644 index 00000000..24a2f9aa --- /dev/null +++ b/src/Lanceur.SharedKernel/Mixins/CloningMixin.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Lanceur.SharedKernel.Mixins; + +public static class CloningMixin +{ + #region Methods + + /// + /// Clone object by serialising/deserialising it + /// + /// The object to clone + /// The type of the object to clone + /// A new instance of the object with the same state + public static T CloneObject(this T obj) + where T: new() + { + var bytes = JsonSerializer.SerializeToUtf8Bytes(obj); + return JsonSerializer.Deserialize(bytes); + } + + #endregion Methods +} \ No newline at end of file diff --git a/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs b/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs index 51c5d241..3332a3b1 100644 --- a/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs +++ b/src/Tests/Lanceur.Tests/Utils/Macros/MultiMacroTest.cs @@ -1,11 +1,12 @@ using Lanceur.Core; using Lanceur.Core.Models; using System.ComponentModel; +using Lanceur.SharedKernel.Mixins; namespace Lanceur.Tests.Utils.Macros { [Macro("multi"), Description("Allow to start multiple alias at once")] - public class MultiMacroTest : SelfExecutableQueryResult + public class MultiMacroTest : MacroQueryResult { #region Constructors @@ -21,6 +22,8 @@ public MultiMacroTest(string parameters = null) #region Methods + public override SelfExecutableQueryResult Clone() => this.CloneObject(); + public override Task> ExecuteAsync(Cmdline cmdline = null) { var list = new List diff --git a/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableTestAlias.cs b/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableTestAlias.cs index ecc97423..04c958b0 100644 --- a/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableTestAlias.cs +++ b/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableTestAlias.cs @@ -1,11 +1,12 @@ using Lanceur.Core; using Lanceur.Core.Models; +using Lanceur.SharedKernel.Mixins; using System.ComponentModel; namespace Lanceur.Tests.Utils.ReservedAliases { [ReservedAlias("anothertest"), Description("description")] - public class ExecutableTestAlias : SelfExecutableQueryResult + public class ExecutableTestAlias : MacroQueryResult { #region Constructors @@ -22,6 +23,8 @@ public ExecutableTestAlias() public static ExecutableTestAlias Random() => FromName(Guid.NewGuid().ToString().Substring(0, 8)); + public override SelfExecutableQueryResult Clone() => this.CloneObject(); + public override Task> ExecuteAsync(Cmdline cmdline = null) { Parameters = cmdline.Parameters; diff --git a/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableWithResultsTestAlias.cs b/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableWithResultsTestAlias.cs index 5d46738d..4549f927 100644 --- a/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableWithResultsTestAlias.cs +++ b/src/Tests/Lanceur.Tests/Utils/ReservedAliases/ExecutableWithResultsTestAlias.cs @@ -1,13 +1,16 @@ using Lanceur.Core.Models; +using Lanceur.SharedKernel.Mixins; namespace Lanceur.Tests.Utils.ReservedAliases { - public class ExecutableWithResultsTestAlias : SelfExecutableQueryResult + public class ExecutableWithResultsTestAlias : MacroQueryResult { #region Methods public static ExecutableWithResultsTestAlias FromName(string name) => new() { Name = name, Query = new Cmdline(name) }; + public override SelfExecutableQueryResult Clone() => this.CloneObject(); + public override Task> ExecuteAsync(Cmdline cmdline = null) { var result = new List()