Hey Leute, kurz zur Ausgangssituation:
ich habe ein Programm bzw. eine Library die ich für mehrere Maschinen nutzen möchte.
Das Programm soll Initialisierungsmethoden für verschiedene Hardware beinhalten, unabhängig davon ob die Hardware tatsächlich in der Maschine verbaut ist.
Die eine Maschine hat z.B. ein Wago IO-Modul mit entsprechenden digitalen Ein- bzw. Ausgängen, eine andere hat einen Scanner und ein Multimeter(DMM).
Im Programm sollen dann, wie gesagt unabhängig von der Hardwareausstattung, die Init-Methoden enthalten sein wie
Zu meinem Problem:
Manche Methoden dürfen nur ausgeführt werden, wenn zuvor eine andere ausgeführt wurde. Bsp.:
Für solche Fälle setze ich aktuell ein Attribute ein.
Spoiler anzeigen
Verwendung:
Wie man sieht kann man die Methode über die Attribute-Property
Allerdings hatte ich hier das Problem, dass auch innerhalb einer "Prioritätsgruppe" eine bestimmte Reihenfolge einzuhalten ist.
Müssen beispielsweise die DIs und DOs vor dem Scanner initialisiert werden, wären
Um dieses Problem zu lösen soll die Property
Die Initialisierungsmethoden müssen mit einem bestimmten Identifier beginnen, in dem Fall mit "Init". Auf die einzelnen Attribute-Werte greife ich via Reflection zu.
Für die Sortierung innerhalb einer Prioritätsgruppe verwende ich einen Algorithmus den ich hier gefunden und für meine Zwecke angepasst habe.
Aufruf der sortierten Methoden:
Im Anhang ist noch ein kleines Beispiel-Projekt.
Kann man das so machen oder ist das Pfusch?
Was kann man verbessern/vereinfachen?
ich habe ein Programm bzw. eine Library die ich für mehrere Maschinen nutzen möchte.
Das Programm soll Initialisierungsmethoden für verschiedene Hardware beinhalten, unabhängig davon ob die Hardware tatsächlich in der Maschine verbaut ist.
Die eine Maschine hat z.B. ein Wago IO-Modul mit entsprechenden digitalen Ein- bzw. Ausgängen, eine andere hat einen Scanner und ein Multimeter(DMM).
Im Programm sollen dann, wie gesagt unabhängig von der Hardwareausstattung, die Init-Methoden enthalten sein wie
InitWago
, InitDI
, InitDO
, InitScanner
und InitDMM
.Zu meinem Problem:
Manche Methoden dürfen nur ausgeführt werden, wenn zuvor eine andere ausgeführt wurde. Bsp.:
InitWago
muss zwingend vor InitDI
und InitDO
ausgeführt werden.Für solche Fälle setze ich aktuell ein Attribute ein.
C#-Quellcode
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- namespace DynamischerMethodenAufruf
- {
- [AttributeUsage(AttributeTargets.Method)]
- internal class InitPriorityAttribute : Attribute
- {
- public InitPriorityAttribute(bool enabled, InitPriority priority)
- {
- Priority = priority;
- Enabled = enabled;
- }
- public InitPriorityAttribute(bool enabled, InitPriority priority, string performAfterMethod) : this(enabled, priority)
- {
- PerformAfterMethod = performAfterMethod;
- }
- public enum InitPriority
- {
- Prio1 = 0,
- Prio2
- }
- public bool Enabled { get; private set; }
- public string PerformAfterMethod { get; private set; } = string.Empty;
- public InitPriority Priority { get; private set; }
- private static MethodInfo[] ShellSort(MethodInfo[] array)
- {
- for (int interval = array.Length / 2; interval > 0; interval /= 2)
- {
- for (int i = interval; i < array.Length; i++)
- {
- var item = array[i];
- var k = i;
- while (k >= interval && array[k - interval].Name != item.GetCustomAttribute<InitPriorityAttribute>().PerformAfterMethod)
- {
- array[k] = array[k - interval];
- k -= interval;
- }
- array[k] = item;
- }
- }
- return array;
- }
- public static IEnumerable<MethodInfo> GetSortedMethodInfos(Type type, string identifier)
- {
- var methodInfos = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
- .Where(x => x.Name.StartsWith(identifier) && x.GetCustomAttribute<InitPriorityAttribute>().Enabled)
- .OrderBy(x => x.GetCustomAttribute<InitPriorityAttribute>().Priority);
- return methodInfos.Select(x => x.GetCustomAttribute<InitPriorityAttribute>().Priority).Distinct()
- .SelectMany(x => ShellSort(methodInfos.Where(c => c.GetCustomAttribute<InitPriorityAttribute>().Priority == x).ToArray()));
- }
- }
- }
Verwendung:
Wie man sieht kann man die Methode über die Attribute-Property
Enabled
entweder ausführen lassen oder eben nicht. Über die Property Priority
soll festgelegt werden, in welcher Reihenfolge die Methoden ausgeführt werden.Allerdings hatte ich hier das Problem, dass auch innerhalb einer "Prioritätsgruppe" eine bestimmte Reihenfolge einzuhalten ist.
Müssen beispielsweise die DIs und DOs vor dem Scanner initialisiert werden, wären
InitWago
, InitDI
und InitDO
Prio1 und InitScanner
wäre Prio2. Aber wie gesagt muss InitWago
vor InitDI
ausgeführt werden.Um dieses Problem zu lösen soll die Property
PerformAfterMethod
dienen.Die Initialisierungsmethoden müssen mit einem bestimmten Identifier beginnen, in dem Fall mit "Init". Auf die einzelnen Attribute-Werte greife ich via Reflection zu.
Für die Sortierung innerhalb einer Prioritätsgruppe verwende ich einen Algorithmus den ich hier gefunden und für meine Zwecke angepasst habe.
Aufruf der sortierten Methoden:
Im Anhang ist noch ein kleines Beispiel-Projekt.
Kann man das so machen oder ist das Pfusch?
Was kann man verbessern/vereinfachen?
Dumm ist der, der dumm ist. Nicht andersrum!