Wiederverwendung von Prozessen

Die TAA kennt eine Möglichkeit, um Interaktionsprozesse (wie z.B. die AL-Business-Suite) in einem Geschäftsvorfall wieder zu verwenden, und einen solchen Prozess über neue Interaktionsmodule bzw. das Ende des Geschäftsvorfall zu unterrichten. Hierzu muss der Prozess das neue Interface TeamWiSE.TAA.IEXECLRProcess implementieren:

using System.ServiceModel;
 
namespace TeamWiSE.TAA
{
	/// <summary>
	/// Interface to implement by a remoting object in the process, to communicate with the EXECLR proxy
	/// </summary>
	public interface IEXECLRProcess
	{
		/// <summary>
		/// Return <b>true</b> if the process is currently in use for a module.
		/// </summary>
		bool InUse { get; }
 
		/// <summary>
		/// The numeric id of the process
		/// </summary>
		int Id { get; }
 
		/// <summary>
		/// Invoked to inform the process to act for another module.
		/// </summary>
		/// <param name="Appl">Application of the module to implement</param>
		/// <param name="Module">Name of the module to implement</param>
		/// <param name="Arguments">Arguments from the implementation specification</param>
		void ResumeWith(string Appl, string Module, string Arguments);
 
		/// <summary>
		/// Invoked to inform the process to cleanup.
		/// </summary>
		void Cleanup();
	}
}

Wie aus der Definition dieses Interfaces abzuleiten ist, kann diese Funktionalität nur in .NET für den Implementierungstyp EXECLR verwendet werden. Das Objekt, welches dieses Interface implementiert, wird mittels COM von der EXECLR-Proxy verwendet, um den Prozess zu unterrichten. Damit die EXECLR-Proxy dieses Objekt verwenden kann, ist die TeamWiSE.TAA.taaEnv-Klasse um eine statische Methode RegisterProcess erweitert worden:

namespace TeamWiSE.TAA
{
	public class taaEnv
	{
		<snip>...</snip>
 
		/// <summary>
		/// Register a process with the EXECLR Proxy
		/// 
		/// </summary>
		/// <param name="bc">BC to register the process for</param>
		/// <param name="proxy">Communication interface to pass to the EXECLR proxy</param>
		/// <returns>
		/// <b>true</b> on success, <b>false</b> on failure
		/// </returns>
		public static bool RegisterProcess(BcObject bc, IEXECLRProcess proxy)
		{
			<snip>...</snip>
		}
	}
}

Da der Prozess nur innerhalb eines Geschäftsvorfall wiederverwendet werden soll, bekommt diese Methode auch eine Referenz auf das BC-Object übergeben. Dieses kann als Eigenschaft Bc von der TeamWiSE.TAA.ModlEnv-Klasse besorgt werden.

Die Implementierungsspezifikation für die Module, die den gleichen Prozess verwenden wollen, müssen alle den gleichen Prozessnamen enthalten. Wenn für einen Geschäftsvorfall noch kein Prozess registriert ist, wird der EXECLR-Proxy wie bisher einen neuen Prozess starten, und die Argumente aus der Implementierungsspezifikation übergeben. Wird aber an Hand des Prozessnamens ein registrierter Prozess gefunden, dann wird dieser über die Methode ResumeWith unterrichtet. Er bekommt neben dem Namen und der Anwendung des Moduls auch die Argumente aus der Implementierungsspezifikation übergeben.

Wenn ein Geschäftsvorfall beendet bzw. unterbrochen wird, werden alle für diesen BC registrierten Prozesse über die Methode Cleanup hiervon unterrichtet.

Hier sehen Sie ein Beispiel, wie eine Implementierungs dieses Interfaces aussehen könnte:

using System;
using System.Diagnostics;
using System.Windows.Forms;
using TeamWiSE.TAA;
 
namespace TWOnly.Interaction
{
	public partial class MainForm : Form
	{
		<snip>...</snip>
		private class EXECLRProcess : MarshalByRefObject, IEXECLRProcess
		{
			// The MainForm we need to inform.
			public MainForm MainForm { get; set; }
 
			// Invoked to inform that the Bc is done, and the process can terminate
			public void Cleanup()
			{
				// shout if a module is still active
				if (this.MainForm.ModlEnv != null)
					throw new InvalidOperationException();
 
				// This will also close the MainForm
				Application.Exit();
			}
 
			// Invoked to retrieve the process id
			public int Id
			{
				get { return Process.GetCurrentProcess().Id; }
			}
 
			// Invoked to check if the process can resume
			public bool InUse
			{
				get { return this.MainForm.ModlEnv != null; }
			}
 
			private delegate void ResumeWithDelegate(string Appl, string Module, string Arguments);
 
			// Invoked to inform us that the process should resume
			public void ResumeWith(string Appl, string Module, string Arguments)
			{
				// as we don't know on which thread we're invoked, use MainForm
				// to invoke ourself on the UI thread
				if (this.MainForm.InvokeRequired) {
					this.MainForm.Invoke(new ResumeWithDelegate(this.ResumeWith), new object[] { Appl, Module, Arguments });
					return;
				}
 
				// shout if a module is still active
				if (this.MainForm.ModlEnv != null)
					throw new InvalidOperationException();
 
				// tell MainForm about the new module
				this.MainForm.Register(Module);
			}
		}
	}
}

Nach einer erfolgreichen Modulregistrierung (i.e. taaRegister-Aufruf) wird eine Instanz dieser Klasse dann mit folgendem Aufruf an die Infrastruktur übergeben:

			taaEnv.RegisterProcess(this.ModlEnv.Bc, new EXECLRProcess { MainForm = this });