-
ActiveEntry Manager Plug-In
Veröffentlicht am 16. November, 2011 in den Kategorien ClipboardDie hier enthaltene Beschreibung basiert auf ActiveEntry 4.1, sollte aber auch in neueren Versionen (inkl. Quest One Identity Manager) funktionieren. Eine Garantie dafür kann selbstverständlich nicht übernommen werden. Alle Änderungen erfolgen auf eigene Verantwortung.
Ganz ähnlich, wie das Plug-In für den Job-Service, können auch Plug-Ins für den Manager erstellt werden.
Dort lassen diese sich dann über den Menüpunkt “Plugins” aufrufen:
Zum Implementierung muss nur von der Klasse DialogEnginePlugin abgeleitet und das Plug-In über die Konfigurationsdatei bekannt gemacht werden.
Je Plug-In wird also eine eigene Klasse erstellt. Mehrere Klassen lassen sich dann in einem Assembly (einer DLL) zusammen fassen.
VI.DialogEngine.Plugins.DialogEnginePlugin
Die Basisklasse implementiert das Interfaxe IDialogEnginePlugin und stellt den generellen Rahmen bereit. Wir müssen dann einfach nur noch einige Methoden und Eigenschaften überschreiben:
OnExecute
Wird aufgerufen, wenn der entsprechende Menüpunkt ausgewählt wurde. Parameter werden keine übergeben, man kann jedoch über die Eigenschaften der Basisklasse direkt auf viele Details des Managers zugreifen.
Caption
Über diese Eigenschaft fragt der Manager den Anzeigenamen des Plug-Ins (für den Menüpunkt) ab.
Description
Zusätzlich zum Namen sollte auch eine kurze Beschreibung hinterlegt werden – diese wird über die Eigenschaft Description abgefragt.
Type
Über diese Eigenschaft wird der Typ des Plugins abgefragt. Zurückgben kann man hier DialogPluginType.UserInterface oder DialogPluginType.None – ich habe bisher nur das erste verwendet.
Image
Die im Menü angezeigten Icons müssen einem bestimmten Format entsprechen (vermutlich gelten hier die gleichen Einschränkungen, wie beim Hinzufügen von Icons in der Datenbank). Am einfachsten lassen sich die mitgelieferten Bilder einbinden und zurück liefern:
static CopyPlugIn() { image = new DialogImage("SC.CopyPlugIn", "sc_copy", ImageHandler.GetImage(StockImage.Copy, ImageSize.Small, ImageState.Normal, true), ImageHandler.GetImage(StockImage.Copy, ImageSize.Medium, ImageState.Normal, true)); } public override DialogImage Image { get { return image; } }IComparable
Zusätzlich kann noch das Interface IComparable implementiert werden. Dies geht am besten, wenn man gleich die untypisierte und die generische Variante zusammen implementiert:
public class CopyPlugIn : DialogEnginePlugin, IComparable, IComparable<IDialogEnginePlugin> { public int CompareTo(IDialogEnginePlugin other) { if (other == null || String.IsNullOrEmpty(other.Caption)) return 1; return this.Caption.CompareTo(other.Caption); } public int CompareTo(object obj) { return this.CompareTo(obj as IDialogEnginePlugin); } }Konfiguration
In der Datei Manager.exe.config muss die neue DLL über einen Eintrag im dialogplugins Element eingebunden werden (Zeile 5):
<dialogplugins> <add key="ComplianceRuleSimulation" value="VI.DialogEngine.Plugins.ComplianceRuleSimulation, AE.DialogEngine.Plugins" /> <add key="ComplianceRuleSimulationSummary" value="VI.DialogEngine.Plugins.ComplianceRuleSimulationSummary, AE.DialogEngine.Plugins" /> <add key="SAPRightsFunctionImport" value="VI.DialogEngine.Plugins.SAPRightsFunctionImport, AE.DialogEngine.Plugins" /> <add key="SCCopyPlugIn" value="SC.Idm.AE.PlugIn.CopyPlugIn, SC.Idm.AE.Manager.PlugIn" /> </dialogplugins>
Wenn das Element nicht existiert, kann es einfach ergänz werden (dabei ist aber zu beachten, das der name wie im Beispiel klein geschrieben sein muss).
Verteilung
Um das Plugin allen Benutzern zur Verfügung zu stellen muss die erstellte DLL über den SoftwareLoader in die Datenbank gespeichert werden (nur für GUI). Außerdem muss natürlich auf gleichem Wege auch die Manager.exe.config aktualisiert werden.
Beispiel
Zur Demonstration sollte hier eine Klasse genügen. Da das Plug-In immer gegen die ActiveEntry (/Q1IM)-Bibliotheken der eingesetzten Version kompiliert werden muss, wird hier nur der Quellcode bereit gestellt. Zum Übersetzen sollte Visual C# Express 2010 Edition ausreichen (jede Andere Visual Studio Version geht natürlich auch):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using VI.DialogEngine.Plugins; using VI.Base; using VI.DialogEngine; using VI.MVC; using VI.DB; using VI.ImageLibrary; using System.Windows.Forms; namespace SC.Idm.AE.PlugIn { /// <summary> /// The CopyPlugIn class defines a manager plugin to clone any type of object. /// </summary> public class CopyPlugIn : DialogEnginePlugin, IComparable, IComparable<IDialogEnginePlugin> { static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType); static readonly DialogImage image; #region .cctor static CopyPlugIn() { image = new DialogImage("SC.CopyPlugIn", "sc_copy", ImageHandler.GetImage(StockImage.Copy, ImageSize.Small, ImageState.Normal, true), ImageHandler.GetImage(StockImage.Copy, ImageSize.Medium, ImageState.Normal, true)); } #endregion #region CompareTo /// <summary> /// Compares the current instance with an other object of the same type. /// </summary> /// <param name="other"> /// An object to compare with this instance. /// </param> /// <returns> /// A signed 32 bit integer, representing the relative order of the compared objects - see <see cref="IComparable.CompareTo"/>. /// </returns> public int CompareTo(IDialogEnginePlugin other) { if (other == null || String.IsNullOrEmpty(other.Caption)) return 1; return this.Caption.CompareTo(other.Caption); } /// <summary> /// Compares the current instance with an other object of the same type. /// </summary> /// <param name="other"> /// An object to compare with this instance. /// </param> /// <returns> /// A signed 32 bit integer, representing the relative order of the compared objects - see <see cref="IComparable.CompareTo"/>. /// </returns> public int CompareTo(object obj) { return this.CompareTo(obj as IDialogEnginePlugin); } #endregion #region OnExecute /// <summary> /// Overridden. /// Checks the current state and performs the copy operation when possible. /// </summary> protected override void OnExecute() { ISingleDbObject data = null; // data will hold the currently focused object IDocument source = base.Engine.SelectedDocument; if (source != null) data = source.Value as ISingleDbObject; if (data == null) { // using System.Windows.Forms.MessageBox ist not best practice here - use AE-Wrapper when possible (to enhance cross platform support). MessageBox.Show( LanguageManager.Instance.GetString("SC_CP_NoObject"), LanguageManager.Instance.GetString("SC_CP_InvalidObject"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } base.Engine.BeginBusy(VI.FormBase.BusyTime.Normal, null); try { IConnection con = base.Engine.Connection; IDialogNavigatorService navigator = con.Services.Get(typeof(IDialogNavigatorService)) as IDialogNavigatorService; ISingleDbObject target = con.CreateSingle(data.Tablename); // create new object of same type foreach (IDbColumn col in data.Columns) { if (col.ColDef.IsPK) continue; // don't copy primary key values try { if (data[col.Columnname].CanEdit) target[col.Columnname].NewValue = data[col.Columnname].NewValue; } catch (Exception ex) { log.Warn(String.Format("Unable to copy value of column {0}.", col.Columnname), ex); } } target.ExecuteTemplates(); // update values (some templates may depend on setting order navigator.NavigateTo(target); // focus newly created object } catch (Exception ex) { log.Error("Unexpected Exception!", ex); } finally { base.Engine.EndBusy(); } } #endregion #region Caption /// <summary> /// Returns the caption of the menu entry for the plugin. /// </summary> public override string Caption { get { return LanguageManager.Instance["SC_CP_Caption"]; } } #endregion #region Description /// <summary> /// Returns the description of this plugin. /// </summary> public override string Description { get { return LanguageManager.Instance["SC_CP_Description"]; } } #endregion #region Image /// <summary> /// Returns a DialogImage object containing the image associated with the plugins menue entry. /// </summary> public override DialogImage Image { get { return image; } } #endregion #region Type /// <summary> /// Return the type of this plugin. /// </summary> public override DialogPluginType Type { get { return DialogPluginType.UserInterface; } } #endregion } }Geschrieben von Andreas Schauerte
