diff --git a/src/Moryx.ControlSystem/Cells/SessionExtensions.cs b/src/Moryx.ControlSystem/Cells/SessionExtensions.cs
new file mode 100644
index 0000000..5221b32
--- /dev/null
+++ b/src/Moryx.ControlSystem/Cells/SessionExtensions.cs
@@ -0,0 +1,128 @@
+// Copyright (c) 2024, Phoenix Contact GmbH & Co. KG
+// Licensed under the Apache License, Version 2.0
+
+using Moryx.AbstractionLayer.Recipes;
+using Moryx.AbstractionLayer;
+using Moryx.AbstractionLayer.Products;
+using Moryx.ControlSystem.Recipes;
+using System;
+using Moryx.ControlSystem.Processes;
+
+namespace Moryx.ControlSystem.Cells
+{
+ ///
+ /// Extension methods on the to get product related information, activity details or just provide shortcuts based on the actual session type
+ ///
+ public static class SessionExtensions
+ {
+ ///
+ /// Extension method to get the from the of the
+ ///
+ /// Type of the that is expected.
+ /// The sesion to get the from
+ ///
+ /// The in the session, if the belongs to a
+ /// and the holds a ;
+ /// Otherwise returns null
+ ///
+ public static TProductInstance GetProductInstance(this Session session) where TProductInstance : ProductInstance
+ {
+ if (session.Process is not ProductionProcess process) return null;
+
+ return process.ProductInstance as TProductInstance;
+ }
+
+ ///
+ /// Modifies the of type
+ /// on the of the using the given
+ /// .
+ ///
+ /// The expected type of the product instance
+ /// The sessopm holding the product instance
+ /// The action to be executed on the product instance
+ ///
+ ///
+ /// ((var instance) => instance.MyProperty = 1)
+ /// ]]>
+ ///
+ ///
+ /// Thrown if the of the
+ /// does not hold a product instance of type
+ ///
+ /// Thrown if the of the
+ /// is no
+ public static TInstance ModifyProductInstance(this Session session, Action setter)
+ where TInstance : IProductInstance => session.Process.ModifyProductInstance(setter);
+
+ ///
+ /// Tries to modifies the of type
+ /// on the of the using the given
+ /// . Returns false, if the
+ /// operation could not be executed.
+ ///
+ /// The expected type of the product instance
+ /// The sessopm holding the product instance
+ /// The action to be executed on the product instance
+ ///
+ ///
+ /// ((var instance) => instance.MyProperty = 1)
+ /// ]]>
+ ///
+ ///
+ public static bool TryModifyProductInstance(this Session session, Action setter)
+ where TInstance : IProductInstance => session.Process.TryModifyProductInstance(setter);
+
+ ///
+ /// Extension method to get the from the
+ ///
+ /// Type of the that is expected.
+ /// The sesion to get the from
+ ///
+ /// The in the session, if the currently handles an
+ /// Activity of type ; Otherwise returns null
+ ///
+ public static TActivityType GetActivity(this Session session) where TActivityType : Activity
+ {
+ if (session is ActivityCompleted completed)
+ return completed.CompletedActivity as TActivityType;
+ if (session is ActivityStart start)
+ return start.Activity as TActivityType;
+
+ return null;
+ }
+
+ ///
+ /// Extension method to get the last from the
+ ///
+ /// Type of the that is expected.
+ /// The sesion to get the from
+ ///
+ /// The last in the session, if the currently handles an
+ /// Activity of type ; Otherwise returns null
+ ///
+ public static TActivityType GetLastActivity(this Session session) where TActivityType : Activity
+ => session.Process.LastActivity() as TActivityType;
+
+ ///
+ /// Extension method to get the from the
+ ///
+ /// Type of the that is expected.
+ /// The session to get the from
+ ///
+ /// The target in the session, if it belongs to a
+ /// or holds an with a ; Otherwise returns null.
+ ///
+ public static TProductType GetProductType(this Session session) where TProductType : ProductType
+ {
+ if (session.Process.Recipe is ISetupRecipe setupRecipe)
+ return setupRecipe.TargetRecipe.Target as TProductType;
+
+ if (session.Process.Recipe is IProductRecipe prodcutRecipe)
+ return prodcutRecipe.Target as TProductType;
+
+ return default;
+ }
+ }
+}
diff --git a/src/Moryx.ControlSystem/Jobs/JobExtensions.cs b/src/Moryx.ControlSystem/Jobs/JobExtensions.cs
new file mode 100644
index 0000000..9637573
--- /dev/null
+++ b/src/Moryx.ControlSystem/Jobs/JobExtensions.cs
@@ -0,0 +1,51 @@
+// Copyright (c) 2024, Phoenix Contact GmbH & Co. KG
+// Licensed under the Apache License, Version 2.0
+
+using Moryx.AbstractionLayer.Recipes;
+using Moryx.ControlSystem.Recipes;
+using Moryx.ControlSystem.Setups;
+
+namespace Moryx.ControlSystem.Jobs
+{
+ ///
+ /// Extensions methods for s.
+ ///
+ public static class JobExtensions
+ {
+ ///
+ /// Checks whether the is an
+ /// and gets the predicted failure count; otherwise returns 0.
+ ///
+ public static int CountPredictedFailures(this Job job)
+ {
+ if (job is IPredictiveJob predictiveJob)
+ return predictiveJob.PredictedFailures.Count;
+
+ return 0;
+ }
+
+ ///
+ /// Checks if the references an
+ ///
+ public static bool IsProduction(this Job job) => job.Recipe is IProductionRecipe;
+
+ ///
+ /// Checks if the references an
+ ///
+ public static bool IsSetup(this Job job) => job.Recipe is ISetupRecipe;
+
+ ///
+ /// Checks if the holds an
+ /// that is set to be executed
+ ///
+ public static bool IsPreparingSetup(this Job job)
+ => job.Recipe is ISetupRecipe setup && setup.Execution == SetupExecution.BeforeProduction;
+
+ ///
+ /// Checks if the holds an
+ /// that is set to be executed
+ ///
+ public static bool IsCleaningUpSetup(this Job job)
+ => job.Recipe is ISetupRecipe setup && setup.Execution == SetupExecution.AfterProduction;
+ }
+}
diff --git a/src/Moryx.ControlSystem/Processes/IProcessExtensions.cs b/src/Moryx.ControlSystem/Processes/IProcessExtensions.cs
new file mode 100644
index 0000000..56d30c8
--- /dev/null
+++ b/src/Moryx.ControlSystem/Processes/IProcessExtensions.cs
@@ -0,0 +1,70 @@
+using Moryx.AbstractionLayer.Products;
+using Moryx.AbstractionLayer;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Moryx.ControlSystem.Processes
+{
+ ///
+ /// Extensions on an
+ ///
+ public static class IProcessExtensions
+ {
+ ///
+ /// Modifies the of type
+ /// on the using the given .
+ ///
+ /// The expected type of the product instance
+ /// The process holding the product instance
+ /// The action to be executed on the product instance
+ ///
+ ///
+ /// ((var instance) => instance.MyProperty = 1)
+ /// ]]>
+ ///
+ ///
+ /// Thrown if the given does
+ /// not hold a product instance of type
+ /// Thrown if the given
+ /// is no
+ public static TInstance ModifyProductInstance(this IProcess process, Action setter)
+ where TInstance : IProductInstance
+ {
+ if (process is not ProductionProcess productionProcess)
+ throw new InvalidOperationException($"Cannot modify an {nameof(IProductInstance)} on a process of type {process.GetType()}");
+ if (productionProcess.ProductInstance is not TInstance instance)
+ throw new InvalidCastException($"Cannot cast {nameof(ProductionProcess.ProductInstance)} of type " +
+ $"{productionProcess?.ProductInstance?.GetType()} to {typeof(TInstance)}");
+ setter.Invoke(instance);
+ return instance;
+ }
+
+ ///
+ /// Tries to modifies the of type
+ /// on the using the given . Returns false, if the
+ /// operation could not be executed.
+ ///
+ /// The expected type of the product instance
+ /// The process holding the product instance
+ /// The action to be executed on the product instance
+ ///
+ ///
+ /// ((var instance) => instance.MyProperty = 1)
+ /// ]]>
+ ///
+ ///
+ public static bool TryModifyProductInstance(this IProcess process, Action setter)
+ where TInstance : IProductInstance
+ {
+ if (process is not ProductionProcess productionProcess)
+ return false;
+ if (productionProcess.ProductInstance is not TInstance instance)
+ return false;
+ setter.Invoke(instance);
+ return true;
+ }
+ }
+}
diff --git a/src/Moryx.ControlSystem/Processes/ProcessHolderExtensions.cs b/src/Moryx.ControlSystem/Processes/ProcessHolderExtensions.cs
index b8dfc61..fa08f5f 100644
--- a/src/Moryx.ControlSystem/Processes/ProcessHolderExtensions.cs
+++ b/src/Moryx.ControlSystem/Processes/ProcessHolderExtensions.cs
@@ -11,121 +11,117 @@ namespace Moryx.ControlSystem.Processes
///
public static class ProcessHolderExtensions
{
+ #region Get Position
///
- /// Get the position by number
+ /// Get the position by its
///
- public static TPosition GetPositionByIdentifier(this IProcessHolderGroup group, string identifier)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(group.Positions, t => t.Identifier == identifier);
- }
+ public static TPosition GetPositionByIdentifier(this IProcessHolderGroup group, string identifier)
+ where TPosition : IProcessHolderPosition => GetPosition(group.Positions, t => t.Identifier == identifier);
///
- /// Get the position by number
+ /// Get the position by its
+ ///
+ public static IProcessHolderPosition GetPositionByIdentifier(this IProcessHolderGroup group, string identifier)
+ => GetPosition(group.Positions, t => t.Identifier == identifier);
+
+ ///
+ /// Get the position by its
///
public static TPosition GetPositionByIdentifier(this IEnumerable positions, string identifier)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(positions, t => t.Identifier == identifier);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(positions, t => t.Identifier == identifier);
///
- /// Get the position by session
+ /// Get the position by its
///
public static TPosition GetPositionBySession(this IProcessHolderGroup group, Session session)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(group.Positions, t => t.Session?.Id == session.Id);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(group.Positions, t => t.Session?.Id == session.Id);
+
+ ///
+ /// Get the position by its
+ ///
+ public static IProcessHolderPosition GetPositionBySession(this IProcessHolderGroup group, Session session)
+ => GetPosition(group.Positions, t => t.Session?.Id == session.Id);
///
- /// Get the position by session
+ /// Get the position by its
///
public static TPosition GetPositionBySession(this IEnumerable positions, Session session)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(positions, t => t.Session?.Id == session.Id);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(positions, t => t.Session?.Id == session.Id);
///
- /// Get the position by its process id
+ /// Get the position by its
///
public static TPosition GetPositionByProcessId(this IProcessHolderGroup group, long processId)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(group.Positions, t => t.Process?.Id == processId);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(group.Positions, t => t.Process?.Id == processId);
+
+ ///
+ /// Get the position by its
+ ///
+ public static IProcessHolderPosition GetPositionByProcessId(this IProcessHolderGroup group, long processId)
+ => GetPosition(group.Positions, t => t.Process?.Id == processId);
///
- /// Get the position by its process id
+ /// Get the position by its
///
public static TPosition GetPositionByProcessId(this IEnumerable positions, long processId)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(positions, t => t.Process?.Id == processId);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(positions, t => t.Process?.Id == processId);
///
/// Get the position by id of the running activity
///
public static TPosition GetPositionByActivityId(this IProcessHolderGroup group, long activityId)
- where TPosition : IProcessHolderPosition
- {
- return GetPosition(group.Positions, t => (t.Session as ActivityStart)?.Activity.Id == activityId);
- }
+ where TPosition : IProcessHolderPosition => GetPosition(group.Positions, t => (t.Session as ActivityStart)?.Activity.Id == activityId);
///
- /// Checks if the group holds a process with a finished activity having the matching result
- ///
- public static bool HasFinishedActivity(this IProcessHolderGroup group, long activityId, long activityResult)
- where TPosition : IProcessHolderPosition
- {
- return group.Positions.Any(position => position.HasFinishedActivity(activityId, activityResult));
- }
- ///
- /// Checks if the position holds a process with a finished activity having the matching result.
+ /// Get the position by id of the running activity
///
- public static bool HasFinishedActivity(this IProcessHolderPosition holderPosition, long activityId, long activityResult)
- {
- return holderPosition.Process?.GetActivities(activity => activity.Id == activityId && activity.Result?.Numeric == activityResult).Any() == true;
- }
+ public static IProcessHolderPosition GetPositionByActivityId(this IProcessHolderGroup group, long activityId)
+ => GetPosition(group.Positions, t => (t.Session as ActivityStart)?.Activity.Id == activityId);
///
/// Get the position by id of the running activity
///
public static TPosition GetPositionByActivityId(this IEnumerable positions, long activityId)
- where TPosition : IProcessHolderPosition
+ where TPosition : IProcessHolderPosition => GetPosition(positions, t => (t.Session as ActivityStart)?.Activity.Id == activityId);
+
+ ///
+ /// Tries to get an empty from the
+ ///
+ /// The group to search
+ /// When this method returns, contains the first empty
+ /// , if any is found; otherwise null
+ ///
+ /// true if an empty was found; otherwise, false.
+ ///
+ public static bool TryGetEmptyPosition(this IProcessHolderGroup group, out IProcessHolderPosition position)
{
- return GetPosition(positions, t => (t.Session as ActivityStart)?.Activity.Id == activityId);
+ foreach (var possible in group.Positions)
+ {
+ if (!possible.IsEmpty())
+ continue;
+ position = possible;
+ return true;
+ }
+ position = default;
+ return false;
}
private static TPosition GetPosition(IEnumerable positions, Func filter)
- where TPosition : IProcessHolderPosition
- {
- return positions.SingleOrDefault(filter);
- }
+ where TPosition : IProcessHolderPosition => positions.SingleOrDefault(filter);
+
+ #endregion
+
+ #region Get or Create Sessions
///
/// Try cast and return the holders session property
///
public static TSession ConvertSession(this IProcessHolderPosition holderPosition)
- where TSession : Session
- {
- return holderPosition.Session as TSession;
- }
-
- ///
- /// Access tracing of the current activity
- ///
- public static TTracing Tracing(this IProcessHolderPosition position)
- where TTracing : Tracing, new()
- {
- var currentActivity = (position.Session as ActivityStart)?.Activity;
- return currentActivity?.TransformTracing();
- }
+ where TSession : Session => holderPosition.Session as TSession;
///
- /// Create sessions for all positions on a holder group, that have a process
+ /// Get or create a session for the , if it holds a process. Otherwise returns an empty enumerable.
+ /// This is usually used when attaching to the control system.
///
public static IEnumerable Attach(this ProcessHolderPosition position)
{
@@ -136,43 +132,148 @@ public static IEnumerable Attach(this ProcessHolderPosition position)
}
///
- /// Create sessions for all positions on a holder group, that have a process
+ /// Get or create sessions for all that have a process.
+ /// This is usually used when attaching to the control system.
///
- public static IEnumerable Attach(this IEnumerable positions)
- {
- return positions.SelectMany(p => p.Attach());
- }
+ public static IEnumerable Attach(this IEnumerable positions)
+ => positions.SelectMany(p => p.Attach());
///
- /// Create sessions for all positions on a holder group, that have a process
+ /// Get or create sessions for all that have a process.
+ /// This is usually used when attaching to the control system.
///
- public static IEnumerable Detach(this ProcessHolderPosition position)
+ public static IEnumerable Attach(this IProcessHolderGroup group)
{
- return position.Session != null ? new[] { position.Session } : Enumerable.Empty();
+ var sessions = new List();
+ foreach(var position in group.Positions)
+ {
+ if (position.Session is not null)
+ {
+ sessions.Add(position.Session);
+ continue;
+ }
+
+ if (position.Process is null)
+ continue;
+
+ if (position is ProcessHolderPosition php)
+ sessions.Add(php.StartSession());
+ }
+ return sessions;
}
///
- /// Create sessions for all positions on a holder group, that have a process
+ /// Get a session if has one. Otherwise returns an empty enumerable.
+ /// This is usually used when detaching from the control system.
///
- public static IEnumerable Detach(this IEnumerable positions)
- {
- return positions.Where(p => p.Session != null).Select(p => p.Session);
- }
+ public static IEnumerable Detach(this ProcessHolderPosition position)
+ => position.Session != null ? new[] { position.Session } : Enumerable.Empty();
///
- /// Assign process and session to this position
+ /// Gets the session from each in the
+ /// that holds one. This is usually used when detaching from the control system.
///
- public static void Mount(this IProcessHolderPosition position, IProcess process)
- {
- position.Mount(new MountInformation(process, null));
- }
+ public static IEnumerable Detach(this IEnumerable positions)
+ => positions.Where(p => p.Session != null).Select(p => p.Session);
+
+ ///
+ /// Gets the session from each in the
+ /// that holds one. This is usually used when detaching from the control system.
+ ///
+ public static IEnumerable Detach(this IProcessHolderGroup group)
+ => group.Positions.Where(p => p.Session != null).Select(p => p.Session);
+
+ #endregion
+
+ #region Mounting
+
+ ///
+ /// Assign a to this position
+ ///
+ public static void Mount(this IProcessHolderPosition position, IProcess process)
+ => position.Mount(new MountInformation(process, null));
+
+ ///
+ /// Assign a to this position
+ ///
+ public static void Mount(this IProcessHolderPosition position, Session session)
+ => position.Mount(new MountInformation(null, session));
+
+ ///
+ /// Assign and to this position
+ ///
+ public static void Mount(this IProcessHolderPosition position, IProcess process, Session session)
+ => position.Mount(new MountInformation(process, session));
+
+ #endregion
+
+ #region Status Checks
+
+ ///
+ /// Checks if the has no empty
+ ///
+ public static bool IsFull(this IProcessHolderGroup group)
+ => group.Positions.All(position => !position.IsEmpty());
+
+ ///
+ /// Checks if the has no filled
+ ///
+ public static bool IsEmpty(this IProcessHolderGroup group)
+ => group.Positions.All(position => position.IsEmpty());
+
+ ///
+ /// True if the has neither a nor a
+ /// ; false otherwise.
+ ///
+ public static bool IsEmpty(this IProcessHolderPosition position)
+ => position.Process is null && position.Session is null;
///
- /// Assign process and session to this position
+ /// Checks if the group holds a process with a finished activity having the matching result
+ ///
+ public static bool HasFinishedActivity(this IProcessHolderGroup group, long activityId, long activityResult)
+ where TPosition : IProcessHolderPosition => group.Positions.Any(position => position.HasFinishedActivity(activityId, activityResult));
+
+ ///
+ /// Checks if the position holds a process with a finished activity having the matching result.
///
- public static void Mount(this IProcessHolderPosition position, IProcess process, Session session)
+ public static bool HasFinishedActivity(this IProcessHolderPosition holderPosition, long activityId, long activityResult)
+ => holderPosition.Process?.GetActivities(activity => activity.Id == activityId && activity.Result?.Numeric == activityResult).Any() == true;
+
+ #endregion
+
+ ///
+ /// Access tracing of the current activity
+ ///
+ public static TTracing Tracing(this IProcessHolderPosition position)
+ where TTracing : Tracing, new() => (position.Session as ActivityStart)?.Activity?.TransformTracing();
+
+ ///
+ /// Updates and by resetting the
+ /// and remounting the . For s
+ /// a direct update of the session and process is done on the object.
+ ///
+ /// The position to update
+ /// The updated session on the position
+ /// Thrown if the given does not match
+ /// the session on the
+ public static void Update(this IProcessHolderPosition position, Session session)
{
- position.Mount(new MountInformation(process, session));
+ if (position.Session.Id != session.Id)
+ throw new InvalidOperationException($"Tried to update the {nameof(Session)} on an " +
+ $"{nameof(IProcessHolderPosition)} with a different session. Make sure to " +
+ $"{nameof(IProcessHolderPosition.Reset)} the {nameof(IProcessHolderPosition)} before " +
+ $"assigning a new {nameof(Session)}");
+
+ if (position is ProcessHolderPosition explicitPosition)
+ {
+ explicitPosition.Session = session;
+ explicitPosition.AssignProcess(session.Process);
+ return;
+ }
+
+ position.Reset();
+ position.Mount(session.Process, session);
}
}
}
\ No newline at end of file
diff --git a/src/Moryx.ControlSystem/Recipes/IRecipeExtensions.cs b/src/Moryx.ControlSystem/Recipes/IRecipeExtensions.cs
new file mode 100644
index 0000000..2611657
--- /dev/null
+++ b/src/Moryx.ControlSystem/Recipes/IRecipeExtensions.cs
@@ -0,0 +1,27 @@
+// Copyright (c) 2021, Phoenix Contact GmbH & Co. KG
+// Licensed under the Apache License, Version 2.0
+
+using Moryx.AbstractionLayer.Recipes;
+using System;
+
+namespace Moryx.ControlSystem.Recipes
+{
+ ///
+ /// Extensions on s
+ ///
+ public static class IRecipeExtensions
+ {
+ ///
+ /// Gets a string concatinating order and operation number from an
+ /// or and empty string if none could be found.
+ ///
+ /// An that implements
+ /// or an targeting an
+ /// Separation char between order number and operation number
+ public static string GetOrderOperationString(this IRecipe recipe, string seperator = "-")
+ {
+ var target = (recipe is ISetupRecipe setup ? setup.TargetRecipe : recipe) as IOrderBasedRecipe;
+ return $"{target?.OrderNumber}{(target is null ? "" : seperator)}{target?.OperationNumber}";
+ }
+ }
+}
diff --git a/src/Moryx.ControlSystem/VisualInstructions/VisualInstructorExtensions.cs b/src/Moryx.ControlSystem/VisualInstructions/VisualInstructorExtensions.cs
index 5010ed0..326ff59 100644
--- a/src/Moryx.ControlSystem/VisualInstructions/VisualInstructorExtensions.cs
+++ b/src/Moryx.ControlSystem/VisualInstructions/VisualInstructorExtensions.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Data.Common;
using System.Linq;
using System.Reflection;
using Moryx.AbstractionLayer;
@@ -22,7 +21,7 @@ public static class VisualInstructorExtensions
///
public static long Display(this IVisualInstructor instructor, string title, IVisualInstructions parameter)
{
- return instructor.Display(new ActiveInstruction
+ return instructor.Display(new ActiveInstruction
{
Title = title,
Instructions = parameter.Instructions
@@ -55,6 +54,64 @@ public static long Display(this IVisualInstructor instructor, string title, Acti
});
}
+ ///
+ /// Show a visual instruction text message
+ ///
+ /// The instructor to display the message
+ /// The sender of the message
+ /// The message to be displayed
+ /// The id of the instruction
+ public static long DisplayMessage(this IVisualInstructor instructor, string sender, string message)
+ {
+ return instructor.DisplayMessages(sender, [message]);
+ }
+
+ ///
+ /// Show a set of messages as a visual instruction
+ ///
+ /// The instructor to display the messages
+ /// The sender of the message
+ /// The messages to be displayed
+ /// The id of the instruction
+ public static long DisplayMessages(this IVisualInstructor instructor, string sender, string[] messages)
+ {
+ var instructions = messages.Select(AsInstruction).ToArray();
+ return instructor.Display(new ActiveInstruction
+ {
+ Title = sender,
+ Instructions = instructions
+ });
+ }
+
+ ///
+ /// Show a visual instruction text message
+ ///
+ /// The instructor to display the message
+ /// The sender of the message
+ /// The message to be displayed
+ /// Time after which the message will be cleared
+ public static void DisplayMessage(this IVisualInstructor instructor, string sender, string message, int autoClearMs)
+ {
+ instructor.DisplayMessages(sender, [message], autoClearMs);
+ }
+
+ ///
+ /// Show a set of messages as a visual instruction
+ ///
+ /// The instructor to display the messages
+ /// The sender of the message
+ /// The messages to be displayed
+ /// Time after which the messages will be cleared
+ public static void DisplayMessages(this IVisualInstructor instructor, string sender, string[] messages, int autoClearMs)
+ {
+ var instructions = messages.Select(AsInstruction).ToArray();
+ instructor.Display(new ActiveInstruction
+ {
+ Title = sender,
+ Instructions = instructions
+ }, autoClearMs);
+ }
+
///
/// Execute these instructions based on the given activity and report the result on completion
/// Can (but must not) be cleared with the method
@@ -74,7 +131,7 @@ public static long Execute(this IVisualInstructor instructor, string title, IVis
/// Can (but must not) be cleared with the method
///
/// Type of enum used for possible instruction results
- public static long Execute(this IVisualInstructor instructor, string title, IVisualInstructions parameter, Action callback) where T: Enum
+ public static long Execute(this IVisualInstructor instructor, string title, IVisualInstructions parameter, Action callback) where T : Enum
{
return instructor.Execute(
title,